//注意本题的电话圈是指最大的电话圈,即该电话中再加入任何一个其他人都不能相互可达
#include<cstdio>
#include<vector>
#include<string>
#include<map>
#include<cstring>
using namespace std;
vector<string> names;
int ID(const string& s) { //返回s的编号,即下标
for(int i = 0; i < names.size(); i++)
if(names[i] == s) return i; //s已经存在于names中
names.push_back(s);
return names.size() - 1;
}
const int maxn = 25 + 5;
int n, m, vis[maxn], d[maxn][maxn];
void print(int u) { //打印与u在同一个电话圈的所有人
vis[u] = 1; //避免重复打印
for(int v = 0; v < n; v++)
if(!vis[v] && d[u][v] && d[v][u]) { //v未曾打印,并且u和v相互可达
printf(", %s", names[v].c_str());
vis[v] = 1; //标记v已打印
}
}
int main() {
char s1[99], s2[99];
int kase = 0;
while(scanf("%d%d", &n, &m) == 2 && n) {
names.clear();
memset(d, 0, sizeof(d));
for(int i = 0; i < n; i++) d[i][i] = 1; //默认自身可相互到达
while(m--) {
scanf("%s%s", s1, s2);
d[ID(s1)][ID(s2)] = 1; //s1可到达s2,但s2是否能到达s1未知
}
for(int k = 0; k < n; k++)
for(int i = 0; i < n; i++)
for(int j = 0; j < n; j++)
d[i][j] = d[i][j] || d[i][k] && d[k][j]; //i和j本来就有通路或者借助k形成通路,那么i和j之间就形成通路
if(kase > 0) printf("\n");
printf("Calling circles for data set %d:\n", ++kase);
memset(vis, 0, sizeof(vis)); //每个人只被打印一次,即每个人只属于一个电话圈(最大的电话圈)
for(int i = 0; i < n; i++)
if(!vis[i]) {
printf("%s", names[i].c_str());
print(i); //打印i所在的电话圈的其他人
printf("\n");
}
}
return 0;
}
uva247
最新推荐文章于 2021-02-17 21:35:41 发布