用Floyd算法求出传递闭包,然后用dfs求出每条连通分量。注意其中用到的几个小技巧:
#include<cstdio>
#include<iostream>
#include<cstring>
#include<vector>
#include<set>
#include<map> using namespace std;
vector<string> name;///存储名字
int connect[30][30],vis[30],m,n; int id(string& s) {///用函数标记每个名字对应的id
for(int i=0;i<name.size();i++)
if(name[i]==s) return i;
name.push_back(s);
return name.size() - 1;
} void dfs(int u){///用深搜查找连通分量
vis[u]=1;
for(int v=0;v<n;v++)
if(!vis[v]&&connect[u][v]&&connect[v][u]) {
cout<<", "<<name[v];
dfs(v);
}
} int main()
{
int kase=0;
while(~scanf("%d%d",&n,&m)&&n&&m){
string s1,s2;
int t=0;
memset(connect,0,sizeof(connect));
name.clear();
for(int i=0;i<m;i++){///输入
cin>>s1;
cin>>s2;
connect[id(s1)][id(s2)]=1;///小技巧
}
for(int k=0;k<n;k++)
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
connect[i][j]=connect[i][j]||(connect[i][k]&&connect[k][j]);///Floyd if(kase>0) printf("\n");
printf("Calling circles for data set %d:\n", ++kase); memset(vis,0,sizeof(vis));
for(int i=0;i<n;i++){
if(!vis[i]){
cout<<name[i];
dfs(i);
printf("\n");
}
}
}
return 0;
}