UVA247 - Calling Circles
题目链接:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=183
题意:n个人互相打电话,则说明他们在一个电话圈,即环内,给定n个人和m次通话,将每个环内的人分别输出。
题解:先用Floyd判断传递闭包,然后建立一个新图,将闭包连通的点的边连起来,然后dfs连通块即可。
AC代码:
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <string>
#include <map>
using namespace std;
#define _for(i,a,b) for(int i=a;i<=b;i++)
const int maxn = 30;
int n,m,t,a[maxn][maxn],e[maxn][maxn],vis[maxn];
map<int,string> Q;
map<string,int> E;
void dfs(int x)
{
_for(i,1,n)
{
if(e[x][i]&&vis[i]==0)
{
cout<<", "<<Q[i];
vis[i]=1;
dfs(i);
}
}
}
int main(int argc, char const *argv[])
{
//freopen("now.in","r",stdin);
while(cin>>n>>m)
{
if(n==0&&m==0)break;
if(t!=0)cout<<endl;
_for(i,1,n)vis[i]=0;
E.clear();
Q.clear();
_for(i,1,n)_for(j,1,n)e[i][j]=a[i][j]=0;
int now = 0;
_for(i,1,m)
{
string x,y;
cin>>x>>y;
if(!E.count(x))
{
Q[++now]=x;
E[x]=now;
}
if(!E.count(y))
{
Q[++now]=y;
E[y]=now;
}
a[E[x]][E[y]]=1;
}
_for(k,1,n)
{
_for(i,1,n)
{
_for(j,1,n)a[i][j]=a[i][j]||(a[i][k]&&a[k][j]);
}
}
cout<<"Calling circles for data set "<<++t<<":"<<endl;
_for(i,1,n)
{
_for(j,i+1,n)if(a[i][j]==1&&a[j][i]==1)e[i][j]=1;
}
_for(i,1,n)if(vis[i]==0)
{
cout<<Q[i];
vis[i]=1;
dfs(i);
cout<<endl;
}
}
return 0;
}