-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathLowLink.cpp
More file actions
115 lines (104 loc) · 2.26 KB
/
LowLink.cpp
File metadata and controls
115 lines (104 loc) · 2.26 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
/*
verified by AOJ2172 Escape
LowLink
*/
class UnionFind
{
private:
vector<int> parent;
public:
UnionFind(const int n):parent(vector<int>(n,-1))
{}
const int Find(const int p)
{
return parent[p] < 0 ? p : parent[p] = Find(parent[p]);
}
const void Merge(int p, int q);
const bool Belong(const int p, const int q)
{
return Find(p) == Find(q);
}
const int GetSize(const int p)
{
return -parent[Find(p)];
}
};
const void UnionFind::Merge(int p, int q)
{
p=Find(p);
q=Find(q);
if(p==q) return;
if(parent[p] < parent[q])
{
parent[p] += parent[q];
parent[q]=p;
}
else
{
parent[q] += parent[p];
parent[p]=q;
}
}
struct Edge
{
int to,from,cost;
Edge(int to_,int from_,int weight_):to(to_),from(from_),cost(weight_)
{}
};
typedef vector<Edge> Edges;
typedef vector<Edges> Graph;
const tuple<vector<int>,vector<int>> lowlink(const Graph &g)
{
int n=g.size();
vector<int> order(n), low(n);
vector<char> reach(n);
int cnt=0;
function<int(const int,const int)> dfs=[&](const int v,const int pv)
{
if(reach[v]) return order[v];
reach[v]=true;
order[v]=cnt;
int mlow=cnt;
cnt++;
for(auto&& e:g[v])
{
if(e.to==pv) continue;
mlow=min(mlow, dfs(e.to, v));
}
return low[v]=mlow;
};
dfs(0, -1);
return make_tuple(order, low);
//order[e.from]<low[e.to]のとき、eは橋
}
//縮約後の頂点番号,頂点数
const tuple<vector<int>, int> biconnectedComponent(const Graph &g)
{
int n=g.size();
vector<int> ord, low;
tie(ord, low)=lowlink(g);
UnionFind uf(n);
for(int i=0;i<n;i++)
for(auto&& e:g[i])
if(!(ord[e.from]<low[e.to] || ord[e.to]<low[e.from]))
uf.Merge(e.from, e.to);
vector<int> bc_map(n,-1);
int k=0;
REP(i,n)
{
int j=uf.Find(i);
if(bc_map[j]==-1)
bc_map[j]=k++;
bc_map[i]=bc_map[j];
}
return make_tuple(bc_map, k);
}
const Graph tree_from_BC(int tree_size, const Graph &g, const vector<int> &bc_map)
{
Graph ret(tree_size);
for(int i=0;i<g.size();i++)
for(auto&& e:g[i])
if(bc_map[e.from]!=bc_map[e.to])
ret[bc_map[e.from]].push_back(Edge(bc_map[e.to], bc_map[e.from], e.cost));
return ret;
}