Uva247 Floyd传递闭包+map处理
链接: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;; } } } }