题目大意:
如果两个人互相打电话(直接或者间接),则说他们在同一个电话圈里。例如,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; }