UVA 247"Calling Circles"(floyd求传递闭包+SCC)
题意:
如果两个人相互打电话(直接或间接),则说他们在同一个电话圈里。
(a,b) 表示 a 打给 b;
例如,(a,b),(b,c),(c,d),(d,a),则这四个人在同一个电话圈里;
输入 n(n≤25) 个人的 m 次电话,找出所有的电话圈,输出每个电话圈里的人名(无序)。
题解:
首先用floyd求出传递闭包,构造新图;
然后在新图上跑一遍SCC求解;
AC代码:
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define memF(a,b,n) for(int i=0;i <= n;a[i]=b,++i); 4 const int maxn=30; 5 6 int n,m; 7 int num; 8 int head[maxn]; 9 struct Edge 10 { 11 int to; 12 int next; 13 }G[maxn*maxn*2]; 14 void addEdge(int u,int v) 15 { 16 G[num]={v,head[u]}; 17 head[u]=num++; 18 } 19 map<string ,int >f; 20 map<int ,string >g; 21 bitset<maxn>_bit[maxn]; 22 int col[maxn]; 23 struct SCC 24 { 25 vector<int >vs; 26 bool vis[maxn]; 27 void DFS(int u) 28 { 29 vis[u]=true; 30 for(int i=head[u];~i;i=G[i].next) 31 { 32 int v=G[i].to; 33 if(vis[v] || (i&1)) 34 continue; 35 DFS(v); 36 } 37 vs.push_back(u); 38 } 39 void RDFS(int u,int k) 40 { 41 vis[u]=true; 42 col[u]=k; 43 for(int i=head[u];~i;i=G[i].next) 44 { 45 int v=G[i].to; 46 if(vis[v] || !(i&1)) 47 continue; 48 RDFS(v,k); 49 } 50 } 51 void scc() 52 { 53 vs.clear(); 54 memF(vis,false,n); 55 for(int i=1;i <= n;++i) 56 if(!vis[i]) 57 DFS(i); 58 59 memF(vis,false,n); 60 int k=0; 61 for(int i=vs.size()-1;i >= 0;--i) 62 if(!vis[vs[i]]) 63 RDFS(vs[i],++k); 64 } 65 }_scc; 66 vector<int >vs[maxn]; 67 void Solve() 68 { 69 for(int i=1;i <= n;++i)///传递闭包 70 for(int j=1;j <= n;++j) 71 if(_bit[j][i]) 72 _bit[j] |= _bit[i]; 73 for(int i=1;i <= n;++i)///构图 74 for(int j=1;j <= n;++j) 75 if(_bit[i][j]) 76 { 77 addEdge(i,j); 78 addEdge(j,i); 79 } 80 _scc.scc(); 81 for(int i=1;i <= n;++i) 82 vs[i].clear(); 83 for(int i=1;i <= n;++i) 84 vs[col[i]].push_back(i); 85 86 for(int i=1;i <= n;++i) 87 { 88 bool flag=false; 89 for(int j=0;j < vs[i].size();++j) 90 { 91 if(!flag) 92 { 93 cout<<g[vs[i][j]]; 94 flag=true; 95 } 96 else 97 cout<<", "<<g[vs[i][j]]; 98 } 99 if(flag) 100 printf("\n"); 101 } 102 } 103 void Init() 104 { 105 num=0; 106 memF(head,-1,n); 107 f.clear(); 108 g.clear(); 109 for(int i=0;i <= n;++i) 110 _bit[i].reset(); 111 } 112 int main() 113 { 114 // freopen("C:\\Users\\hyacinthLJP\\Desktop\\in&&out\\contest","r",stdin); 115 bool flag=false; 116 int kase=0; 117 while(~scanf("%d%d",&n,&m) && n+m) 118 { 119 Init(); 120 int k=0; 121 for(int i=1;i <= m;++i) 122 { 123 string s1,s2; 124 cin>>s1>>s2; 125 if(!f.count(s1)) 126 { 127 f[s1]=++k; 128 g[k]=s1; 129 } 130 if(!f.count(s2)) 131 { 132 f[s2]=++k; 133 g[k]=s2; 134 } 135 _bit[f[s1]].set(f[s2]); 136 } 137 if(flag) 138 printf("\n"); 139 flag=true; 140 printf("Calling circles for data set %d:\n",++kase); 141 Solve(); 142 } 143 return 0; 144 }