Codeforces732F Tourist Reform
求出无向图的所有边双联通分量,然后缩点就成了一颗树。
然后我们选取最大的那个边双联通分量作为根,这样我们就可以确定所有割边的方向了。
对于边双联通分量里面的边,我们随便dfs一下就可以把它变成强连通分量,方向也就确定了。
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 vector<int> G[400010]; 5 vector<pair<int, int>> G2[400010]; 6 set<pair<int, int>> bridge; 7 set<pair<int, int>> ansset; 8 pair<int, int> old[400010]; 9 int vis[400010]; 10 int dfn[400010]; 11 int low[400010]; 12 int tag[400010]; 13 14 void get_bridge(int cur, int father, int dep) 15 { 16 vis[cur] = 1; 17 dfn[cur] = low[cur] = dep; 18 int children = 0; 19 for (auto to : G[cur]) 20 { 21 if (to != father && vis[to] == 1) 22 { 23 if (dfn[to] < low[cur]) 24 low[cur] = dfn[to]; 25 } 26 if (vis[to] == 0) 27 { 28 get_bridge(to, cur, dep + 1); 29 children++; 30 if (low[to] < low[cur]) 31 low[cur] = low[to]; 32 if (low[to] > dfn[cur]) 33 bridge.insert({cur, to}), bridge.insert({to, cur}); 34 } 35 } 36 vis[cur] = 2; 37 } 38 39 int dfs(int u, int tot) 40 { 41 int cnt = 1; 42 vis[u] = true; 43 tag[u] = tot; 44 for (auto to : G[u]) 45 { 46 if (ansset.find({u, to}) == ansset.end() && ansset.find({to, u}) == ansset.end() && bridge.find({u, to}) == bridge.end()) 47 { 48 ansset.insert({u, to}); 49 if (!vis[to]) 50 cnt += dfs(to, tot); 51 } 52 } 53 return cnt; 54 } 55 56 void dfs2(int cur, int fa) 57 { 58 for (auto e : G2[cur]) 59 { 60 int nxt = tag[e.second]; 61 if (nxt != fa) 62 { 63 ansset.insert({e.second, e.first}); 64 dfs2(nxt, cur); 65 } 66 } 67 } 68 69 int main() 70 { 71 int n, m; 72 scanf("%d%d", &n, &m); 73 int u, v; 74 for (int i = 0; i < m; i++) 75 { 76 scanf("%d%d", &u, &v); 77 G[u].push_back(v); 78 G[v].push_back(u); 79 old[i] = {u, v}; 80 } 81 get_bridge(1, -1, 0); 82 memset(vis, 0, sizeof(vis)); 83 int ans = 0; 84 int tot = 0; 85 int idx = 0; 86 for (int i = 1; i <= n; i++) 87 { 88 if (!vis[i]) 89 { 90 int siz = dfs(i, ++tot); 91 if (siz > ans) 92 ans = siz, idx = tot; 93 } 94 } 95 for (auto e : bridge) 96 G2[tag[e.first]].push_back(e); 97 dfs2(idx, -1); 98 printf("%d\n", ans); 99 for (int i = 0; i < m; i++) 100 { 101 if (ansset.find(old[i]) == ansset.end()) 102 printf("%d %d\n", old[i].second, old[i].first); 103 else 104 printf("%d %d\n", old[i].first, old[i].second); 105 } 106 return 0; 107 }