求SCC缩点,统计出每个SCC中的点的个数。
然后统计能到达u的最多的点的个数,可以反向建图,再dfs一遍统计出来。
最后说一下,有必要开一个标记数组,因为测试数据中有重边,结果无限WA。
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 #include <vector> 6 #include <stack> 7 using namespace std; 8 9 const int maxn = 5000 + 10; 10 int n, m; 11 vector<int> G[maxn]; 12 13 stack<int> S; 14 int pre[maxn], lowlink[maxn], sccno[maxn], sz[maxn], dfs_clock, scc_cnt; 15 16 void dfs(int u) 17 { 18 pre[u] = lowlink[u] = ++dfs_clock; 19 S.push(u); 20 21 for(int i = 0; i < G[u].size(); i++) 22 { 23 int v = G[u][i]; 24 if(!pre[v]) 25 { 26 dfs(v); 27 lowlink[u] = min(lowlink[u], lowlink[v]); 28 } 29 else if(!sccno[v]) lowlink[u] = min(lowlink[u], pre[v]); 30 } 31 32 if(pre[u] == lowlink[u]) 33 { 34 scc_cnt++; 35 for(;;) 36 { 37 int x = S.top(); S.pop(); 38 sccno[x] = scc_cnt; 39 sz[scc_cnt]++; 40 if(x == u) break; 41 } 42 } 43 } 44 45 void find_scc() 46 { 47 dfs_clock = scc_cnt = 0; 48 memset(pre, 0, sizeof(pre)); 49 memset(sccno, 0, sizeof(sccno)); 50 memset(sz, 0, sizeof(sz)); 51 for(int i = 0; i < n; i++) if(!pre[i]) dfs(i); 52 } 53 54 int support[maxn]; 55 int indeg[maxn]; 56 bool vis[maxn]; 57 vector<int> G2[maxn]; 58 59 int dfs2(int u) 60 { 61 int ans = sz[u]; 62 vis[u] = true; 63 for(int i = 0; i < G2[u].size(); i++) 64 { 65 int v = G2[u][i]; 66 if(vis[v]) continue; 67 ans += dfs2(v); 68 } 69 return ans; 70 } 71 72 int main() 73 { 74 int T; scanf("%d", &T); 75 for(int kase = 1; kase <= T; kase++) 76 { 77 scanf("%d%d", &n, &m); 78 for(int i = 0; i < n; i++) G[i].clear(); 79 while(m--) 80 { 81 int u, v; scanf("%d%d", &u, &v); 82 G[u].push_back(v); 83 } 84 85 find_scc(); 86 87 memset(indeg, 0, sizeof(indeg)); 88 for(int i = 1; i <= scc_cnt; i++) G2[i].clear(); 89 for(int i = 0; i < n; i++) 90 for(int j = 0; j < G[i].size(); j++) 91 { 92 int u = sccno[i], v = sccno[G[i][j]]; 93 if(u == v) continue; 94 indeg[u]++; 95 G2[v].push_back(u); 96 } 97 98 int ans = 0; 99 for(int i = 1; i <= scc_cnt; i++) if(!indeg[i]) 100 { 101 memset(vis, false, sizeof(vis)); 102 support[i] = dfs2(i); 103 ans = max(ans, support[i]); 104 } 105 106 printf("Case %d: %d\n", kase, ans - 1); 107 bool flag = false; 108 for(int i = 0; i < n; i++) 109 { 110 int u = sccno[i]; 111 if(!indeg[u] && support[u] == ans) 112 { 113 if(flag) printf(" "); 114 printf("%d", i); 115 flag = true; 116 } 117 } 118 puts(""); 119 } 120 121 return 0; 122 }
代码君
时间: 2024-10-22 03:52:56