UVa274 Calling Circles(Floyd算法)

题目链接:https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&category=424&page=show_problem&problem=3187

题目大意:共有n个人,n<=25,如果两个人互相打电话(直接或间接),则称他们在同一个电话圈中,如a打给b,b打给c,c打给d,d打给a,则这四个人在同一个圈里;如a给b打,b不给a打(直接或间接),则a、b不在同一个圈中。给出m条通话情况,求出各个电话圈中的所有人。

分析:显然可以构造一个有向图,若两点互相有通路,则在同一个电话圈中,可以用Floyd先求出任意两点是否能互相到达,再输出各个分量的名字。在这里输出时用dfs把每个强连通分量遍历输出。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<string>
 5 #include<map>
 6 using namespace std;
 7 const int Maxn=30;
 8 int n,m,d[Maxn][Maxn],kase=0,have[Maxn];
 9 string num[Maxn];
10 //vector<int> G[Maxn];
11 map<string,int>name;
12 void read(){
13     int count=0;
14     memset(d,0,sizeof(d));
15     for(int i=0;i<m;i++){
16         string s1,s2;
17         cin>>s1>>s2;
18         if(!name.count(s1)){name[s1]=count;num[count++]=s1;}
19         if(!name.count(s2)){name[s2]=count;num[count++]=s2;}
20         d[name[s1]][name[s2]]=1;
21     }
22 }
23 void Floyd(){
24     for(int k=0;k<n;k++){
25         for(int i=0;i<n;i++){
26             for(int j=0;j<n;j++){
27                 d[i][j]=d[i][j]||(d[i][k]&&d[k][j]);
28             }
29         }
30     }
31 }
32 bool dfs(int s,bool first){
33     if(have[s])return false;
34     if(!first)cout<<", ";
35     cout<<num[s];
36     have[s]=1;
37     for(int i=0;i<n;i++){
38         if(s==i)continue;
39         if(d[s][i]&&d[i][s]&&!have[i]){
40             dfs(i,false);
41         }
42     }
43     return true;
44 }
45 int main(){
46     while(cin>>n>>m&&n&&m){
47         name.clear();
48         if(kase)cout<<endl;
49         cout<<"Calling circles for data set "<<++kase<<':'<<endl;
50         read();
51         Floyd();
52         memset(have,0,sizeof(have));
53         for(int i=0;i<n;i++){
54             if(dfs(i,true))cout<<endl;
55         }
56     }
57     return 0;
58 }

 

posted @ 2017-05-17 20:41  7391_KID  阅读(224)  评论(0编辑  收藏  举报