摘自刘汝佳算法紫书
题意:
如果两个人互相打电话(直接或间接),则说他们在同一个电话圈里。例如,a打给b,b打给c,c打给d,d打给a,则这四个人在同一个电话圈里;如果e打给f但f不打给e,则不能推出e和f在同一个电话圈里。输入n(n≤25)个人的m次电话,找出所有的电话圈。人名只包含字母,不超过25个字符,且不重复。
解题思路:
用map存下人名,然后用floyd跑一遍连通性就行了。因为floyd算法是解决任意两点之间的最短距离,这里我们可以用此特性来判断连通性。
代码如下
#include <stdio.h>
#include <algorithm>
#include <cstring>
#include <string>
#include <map>
#include <iostream>
using namespace std;
#define maxn 1005
int d[maxn][maxn],flag[maxn];
int n,m,sum;
int x,y;
string name1,name2;
string nam[maxn];
map<string,int> sim;
void init()
{
sim.clear();
memset(d,0,sizeof(d));
memset(flag,0,sizeof(flag));
sum=0;
}
void input()
{
for(int i=1; i<=m; i++)
{
cin>>name1>>name2;
if(sim.count(name1)) x=sim[name1];
else
{
sim[name1]=++sum;
nam[sum]=name1;
x=sum;
}
if(sim.count(name2)) y=sim[name2];
else
{
sim[name2]=++sum;
nam[sum]=name2;
y=sum;
}
d[x][y]=1;
}
}
void floyd()
{
for(int k=1; k<=n; k++)
for(int i=1; i<=n; i++)
for(int j=1; j<=n; j++)
d[i][j]=d[i][j]||(d[i][k]&&d[k][j]);
}
int main()
{
//freopen("in.txt","r",stdin);
int k=1;
while(~scanf("%d%d",&n,&m)&&n+m)
{
if(k!=1) printf("\n");
printf("Calling circles for data set %d:\n",k++);
init();
input();
floyd();
for(int i=1; i<=n; i++)
{
if(flag[i]) continue;
cout<<nam[i];
for(int j=i+1; j<=n; j++)
{
if(flag[j]) continue;
if(d[i][j]&&d[j][i])
{
flag[j]=1;
cout << ", " <<nam[j];
}
}
cout<<endl;
}
}
return 0;
}