题目大意:
如果两个人互相打电话(直接或者间接),则说他们在同一个电话圈里。例如,a打给b,b打给c,c打给d,d打给a,则这四个人在同一个圈里;如果e打给f但f不打给e,则不能推出e和f在同一个电话圈。输入n(n<=25)个人的m次电话,找出所有的电话圈。人名只包含字母,不超过25个字符,且不重复。
思路:
(传递闭包)
如果一个节点i与j相连,j与k相连,那么i与k相连
就是计算两点是否相互连通
求传递闭包就是把所有这样的点都弄出来
可以用floyd去搞
代码:
#include <bits/stdc++.h>
using namespace std;
map<string,int>indice;
vector<string>name;
int getid(string s){
if(!indice.count(s))indice[s]=name.size(),name.push_back(s);
return indice[s];
}
int main()
{
int n,m;
int t=0;
while(cin>>n>>m){
if(n==0&&m==0)break;
if(t>0)cout<<endl;
int e[30][30]={0},vis[30]={0};
indice.clear(),name.clear();
for(int i=0;i<m;i++){
string a,b;
cin>>a>>b;
e[getid(a)][getid(b)]=1;
}
for(int k=0;k<n;k++){
for(int i=0;i<n;i++){
for(int j=0;j<n;j++)
e[i][j]=e[i][j]||(e[i][k]&&e[k][j]);
}
}
cout<<"Calling circles for data set "<<++t<<":"<<endl;
for(int i=0;i<n;i++){
if(!vis[i]){
cout<<name[i];
vis[i]=1;
for(int j=0;j<n;j++){
if(!vis[j]&&e[i][j]&&e[j][i]){
vis[j]=1;
cout<<", "<<name[j];
}
}
cout<<endl;
}
}
}
return 0;
}

京公网安备 11010502036488号