题目链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=20840
#include <iostream>
#include <string>
#include <cstring>
#include <map>
#include <vector>
using namespace std;
/***************************************************************************************************************
题意:A打给B,B打给A,那么AB就构成了一个电话圈。如果A->B,B->C,C->A,那么这也构成了电话圈,
值得一提的是,如果这种情况下,C->D,D->C,那么D也算是在电话圈内。输出所有的电话圈中的人。
思路:
1,学习了 floyd 的 TC ,可以判断两个点是否在一个圈内(利用floyd求出有向图的传递闭包)
a,初始化相关的两个结点 d[i][j] = 1;
b,d[i][j] = min (d[i][j],d[i][k] + d[k][j]) 改成 d[i][j] = d[i][j] || (d[i][k] && d[k][j])
c,判断依据: d[i][j] == d[j][i] == 1
2,根据传递闭包关系构造新图,输出连通分量中的所有结点
核心:Floyd - TC
**************************************************************************************************************/
int dist[30][30]; //标志两个人是否在同一个圈
int visit[30];
map<string, int> IDcache; // 姓名 -> 编号
string name[30]; // 编号 -> 姓名
int num;
vector <string> ans[30];
//vector<string> name; 这里本来想这么存名字和最后输出的电话圈的,但是push_back老是用不对
//vector<vector<string> > ans; 于是改成上面的,string name[]存名字,vector<string> 存电话圈的人
int ID(string s){
if(IDcache.count(s)) return IDcache[s];
name[++num] = s;
return IDcache[s] = num;
}
int main()
{
int n,m;
int cnt = 0;
while(cin>>n>>m && n && m){
num = 0; //一定要初始化
IDcache.clear(); //一定要初始化
for(int i = 0;i <= n;i ++) ans[i].clear(); //一定要初始化
string s1,s2;
memset(dist,0,sizeof(dist));
for(int i = 1;i <= m;i ++){
cin>>s1>>s2;
int id1 = ID(s1),id2 = ID(s2);
dist[id1][id2] = 1; //相关即为1
}
for(int k = 1;k <= n;k ++)
for(int i = 1;i <= n;i ++)
for(int j = 1;j <= n;j ++)
dist[i][j] = dist[i][j] || (dist[i][k] && dist[k][j]); //Floyd的传递闭包(TC)
memset(visit,0,sizeof(visit));
int len = 0;
for(int i = 1;i <= n;i ++){
if(!visit[i]){
visit[i] = 1;
for(int j = 1;j <= n;j ++){
if(visit[j]) continue;
if(dist[i][j] && dist[i][j] == dist[j][i]){
ans[len].push_back(name[j]);
visit[j] = 1;
}
}
ans[len++].push_back(name[i]);
}
}
if(cnt)
cout<<endl;
cout<<"Calling circles for data set "<<++cnt<<":"<<endl;
for(int i = 0;i < len;i ++){
for(int j = 0;j < ans[i].size();j ++){
if(j) cout<<", ";
cout<<ans[i][j];
}
cout<<endl;
}
}
return 0;
}