UVa - 247 Calling Circles(Floyd - TC)
题目链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=20840
#include <iostream> #include <string> #include <cstring> #include <map> #include <vector> using namespace std; /*************************************************************************************************************** 题意:A打给B,B打给A,那么AB就构成了一个电话圈。如果A->B,B->C,C->A,那么这也构成了电话圈, 值得一提的是,如果这种情况下,C->D,D->C,那么D也算是在电话圈内。输出所有的电话圈中的人。 思路: 1,学习了 floyd 的 TC ,可以判断两个点是否在一个圈内(利用floyd求出有向图的传递闭包) a,初始化相关的两个结点 d[i][j] = 1; b,d[i][j] = min (d[i][j],d[i][k] + d[k][j]) 改成 d[i][j] = d[i][j] || (d[i][k] && d[k][j]) c,判断依据: d[i][j] == d[j][i] == 1 2,根据传递闭包关系构造新图,输出连通分量中的所有结点 核心:Floyd - TC **************************************************************************************************************/ int dist[30][30]; //标志两个人是否在同一个圈 int visit[30]; map<string, int> IDcache; // 姓名 -> 编号 string name[30]; // 编号 -> 姓名 int num; vector <string> ans[30]; //vector<string> name; 这里本来想这么存名字和最后输出的电话圈的,但是push_back老是用不对 //vector<vector<string> > ans; 于是改成上面的,string name[]存名字,vector<string> 存电话圈的人 int ID(string s){ if(IDcache.count(s)) return IDcache[s]; name[++num] = s; return IDcache[s] = num; } int main() { int n,m; int cnt = 0; while(cin>>n>>m && n && m){ num = 0; //一定要初始化 IDcache.clear(); //一定要初始化 for(int i = 0;i <= n;i ++) ans[i].clear(); //一定要初始化 string s1,s2; memset(dist,0,sizeof(dist)); for(int i = 1;i <= m;i ++){ cin>>s1>>s2; int id1 = ID(s1),id2 = ID(s2); dist[id1][id2] = 1; //相关即为1 } for(int k = 1;k <= n;k ++) for(int i = 1;i <= n;i ++) for(int j = 1;j <= n;j ++) dist[i][j] = dist[i][j] || (dist[i][k] && dist[k][j]); //Floyd的传递闭包(TC) memset(visit,0,sizeof(visit)); int len = 0; for(int i = 1;i <= n;i ++){ if(!visit[i]){ visit[i] = 1; for(int j = 1;j <= n;j ++){ if(visit[j]) continue; if(dist[i][j] && dist[i][j] == dist[j][i]){ ans[len].push_back(name[j]); visit[j] = 1; } } ans[len++].push_back(name[i]); } } if(cnt) cout<<endl; cout<<"Calling circles for data set "<<++cnt<<":"<<endl; for(int i = 0;i < len;i ++){ for(int j = 0;j < ans[i].size();j ++){ if(j) cout<<", "; cout<<ans[i][j]; } cout<<endl; } } return 0; }