题目链接:
Calling Circles
刘汝佳紫书单源最短路例题之一。
题目大意:
有一群人打电话。如果有两个人互相打电话(直接或间接:a打给b,b打给c,c打给a,那么称 a 和 c 满是间接关系),求输出所有电话圈。
Limits:<=25
思路:
用 Floyd 算法跑一遍即可,再求出连通分量。具体题目按照Uva惯例,输入输出比较繁琐。
样例输入:
5 6
Ben Alexander
Alexander Dolly
Dolly Ben
Dolly Benedict
Benedict Dolly
Alexander Aaron
1 0
0 0
样例输出:
Calling circles for data set 1:
Ben, Alexander, Dolly, Benedict
Aaron
Calling circles for data set 2:
具体代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair <int,int> pii;
#define mem(s,t) memset(s,t,sizeof(s))
#define D(v) cout<<#v<<" "<<v<<endl
#define inf 0x3f3f3f3f
#define pb push_back
//#define LOCAL
const int mod=1e9+7;
const int MAXN =1000;
int N,M;
int a[MAXN][MAXN],vis[MAXN];
map<string,int> m;
map<int,string> ans;
int main() {
#ifdef LOCAL
//freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
#endif
int kase=0;
while(cin>>N>>M && N+M){
if(kase) puts("");
cout<<"Calling circles for data set "<<++kase<<":\n";
mem(a,0);
mem(vis,0);
m.clear();
ans.clear();
int cnt=1;
for(int i=0;i<M;i++){
string s1,s2;
cin>>s1>>s2;
if(!m[s1]) m[s1]=cnt++,ans[cnt-1]=s1;
if(!m[s2]) m[s2]=cnt++,ans[cnt-1]=s2;
a[m[s1]][m[s2]]=1;
}
//Floyd
for(int k=1;k<=N;k++){
for(int i=1;i<=N;i++){
for(int j=1;j<=N;j++){
a[i][j]=a[i][j]||(a[i][k] && a[k][j]);
}
}
}
//Outputs
for(int i=1;i<=N;i++){
if(vis[i]) continue;
cout<<ans[i];
for(int j=i+1;j<=N;j++){
if(vis[j]) continue;
if(a[i][j] && a[j][i]){
cout<<", "<<ans[j];
vis[j]=1;
}
}
cout<<endl;
}
}
return 0;
}