第一个强连通分量的题。
题意:有一堆人,a给b打电话表示a有一条向b的边,一个强连通分量代表一个电话圈,把每个电话圈里的人在一行内输出出来。
直接上模板即可,但是要注意把string用map映射一下的技巧。
代码如下:
1 #include <stdio.h> 2 #include <algorithm> 3 #include <string.h> 4 #include <string> 5 #include <iostream> 6 #include <vector> 7 #include <map> 8 #include <stack> 9 using namespace std; 10 11 int n,m; 12 vector<string> names; 13 vector<int> G[30]; 14 map<string,int> mp; 15 stack<int> S; 16 int tot; 17 int belong[30],scc_cnt,low[30],dfn[30],dfs_clock; 18 19 void dfs(int u) 20 { 21 dfn[u]=low[u]=++dfs_clock; 22 S.push(u); 23 for(int i=0;i<G[u].size();i++) 24 { 25 int v = G[u][i]; 26 if(!dfn[v]) 27 { 28 dfs(v); 29 low[u]=min(low[u],low[v]); 30 } 31 else if(!belong[v]) 32 { 33 low[u]=min(low[u],low[v]); 34 } 35 } 36 if(dfn[u]==low[u]) 37 { 38 scc_cnt++; 39 for(;;) 40 { 41 int x = S.top();S.pop(); 42 belong[x] = scc_cnt; 43 if(x==u) break; 44 } 45 } 46 } 47 48 void scc() 49 { 50 dfs_clock=scc_cnt=0; 51 memset(belong,0,sizeof(belong)); 52 memset(dfn,0,sizeof(dfn)); 53 for(int i=0;i<n;i++) if(!dfn[i]) dfs(i); 54 } 55 56 void print() 57 { 58 vector<int> ans[30]; 59 for(int i=0;i<n;i++) ans[belong[i]].push_back(i); 60 for(int i=1;i<=scc_cnt;i++) 61 { 62 for(int j=0;j<ans[i].size();j++) 63 { 64 if(j) printf(", "); 65 cout<<names[ans[i][j]]; 66 } 67 puts(""); 68 } 69 } 70 71 int main() 72 { 73 int cnt=1; 74 while(scanf("%d%d",&n,&m)==2) 75 { 76 tot=0; 77 names.clear(); 78 mp.clear(); 79 for(int i=0;i<n;i++) G[i].clear(); 80 if(n==0 && m==0) break; 81 for(int i = 1; i <= m;i++) 82 { 83 string u,v; 84 cin>>u>>v; 85 if(mp.find(u)==mp.end()) mp[u]=tot++,names.push_back(u); 86 if(mp.find(v)==mp.end()) mp[v]=tot++,names.push_back(v); 87 G[mp[u]].push_back(mp[v]); 88 } 89 scc(); 90 91 if(cnt != 1) cout << endl; 92 cout << "Calling circles for data set " << cnt ++ <<":" << endl; 93 //printf("Calling circles for data set %d: ",cnt++); 94 print(); 95 //puts(""); 96 } 97 return 0; 98 }
但是搞不懂的是为什么注释掉的输出部分是错的呢- -