链接:https://vjudge.net/problem/UVA-247
题意:a打给b,b打给c,c打给d,d打给a,那么这四个人就在一个圈里,具有传递性,离散数学传递闭包的经典题目,a可以通过bc到达d,因为d可以到达a,所以a和d在一个圈,b可以通过cd到达a,a也可以到达b,所以ab在一个圈。如果e打给f,f不能直接或者间接打给e,那么这两个人就不在一个圈,找出所有的圈。
n最大才25,不怕超时了,floyd三重循环暴力解决
利用floyd的中间传递松弛性恰好解决。
#include <bits/stdc++.h>
using namespace std;
map<string,int>name;
vector<string>Name;
int n,m;
int vis[30];
int d[30][30];
int id;//没什么用,就是给name逐增赋值
void floyd() {
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]);
}
void dfs(int u) {
vis[u] = 1;
for(int i = 0; i < n; i++) {
if(!vis[i]&&d[u][i]&&d[i][u]) {
cout<<", "<<Name[i];
dfs(i);
}
}
}
int main() {
// freopen("in.txt","r",stdin);
int casen = 1;
while(cin>>n>>m) {
if(n==0&&m==0)
break;
Name.clear();
name.clear();
memset(d,0,sizeof(d));
memset(vis,0,sizeof(vis));
id =0;
while(m--) {
string a,b;
cin>>a>>b;
//count()函数返回map中键值等于key的元素的个数,就只能为
//1或者0,专门判断一个键值值是否存在map里面,前提是这个键值赋了key值。
if(!name.count(a)) {
name[a] = id;
id++;
Name.push_back(a);
}
if(!name.count(b)) {
name[b] = id;
id++;
Name.push_back(b);
}
d[name[a]][name[b]] = 1;
}
floyd();
if(casen>1)
cout<<endl;
printf("Calling circles for data set %d:\n",casen);
casen++;
for(int i = 0; i < n; i++) {
if(!vis[i]) {
cout<<Name[i];
dfs(i);
cout<<endl;;
}
}
}
}