Floyd联通, 然后为了输出联通分量而新建一个图, 让互相可以打电话的建立一条边, 然后dfs输出联通分量就ok了。
#include<cstdio>
#include<iostream>
#include<cstring>
#include<string>
#include<map>
#include<vector>
#define REP(i, a, b) for(int i = (a); i < (b); i++)
using namespace std;
const int MAXN = 30;
int d[MAXN][MAXN], g[MAXN][MAXN], vis[MAXN], n, m;
map<string, int> id;
vector<string> word;
int get_id(string s)
{
if(id.count(s)) return id[s];
word.push_back(s);
return id[s] = word.size() - 1; //注意这里要减去1
}
void print(int u, int p)
{
if(p != 1) printf(", ");
cout << word[u];
vis[u] = 1;
REP(v, 0, n)
if(g[u][v] && !vis[v])
print(v, 0);
}
int main()
{
int kase = 0;
while(~scanf("%d%d", &n, &m) && n && m)
{
if(kase) puts("");
word.clear(); id.clear();
memset(d, 0, sizeof(d));
memset(vis, 0, sizeof(vis));
memset(g, 0, sizeof(g));
while(m--)
{
string a, b;
cin >> a >> b;
d[get_id(a)][get_id(b)] = 1;
}
REP(k, 0, n)
REP(i, 0, n)
REP(j, 0, n)
d[i][j] = d[i][j] || (d[i][k] && d[k][j]);
REP(i, 0, n)
REP(j, 0, n)
g[i][j] = (d[i][j] && d[j][i]);
printf("Calling circles for data set %d:
", ++kase);
REP(i, 0, n)
if(!vis[i])
{
print(i, 1);
puts("");
}
}
return 0;
}