图的连通性问题。两个人相互连通当且仅当两人互相直接或者间接打过电话。因为间接通话的存在,无法直接用dfs来求连通块。要用Floyd算法实现的传递闭包来预处理两人是否直接或间接的通过话。
Floyd算法完后则可以用dfs求出所有连通块了。
Run Time: 0.059s
#define UVa "LT11-4.247.cpp" //Calling Circles
char fileIn[30] = UVa, fileOut[30] = UVa;
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<vector>
#include<iostream>
#include<map>
#include<queue>
using namespace std;
//Global Variables. Reset upon Each Case!
const int maxn = 25 + 5;
int n, m, cnt;
map<string, int> roster;
vector<string> names;
int G[maxn][maxn];
int d[maxn][maxn];
/
int getID(string& name) {
if(roster.count(name)) return roster[name];
names.push_back(name);
return roster[name] = names.size()-1;
}
void floyd() {
memset(d, 0, sizeof(0));
for(int i = 0; i < n; i ++)
for(int j = 0; j < n; j ++)
if(i == j || G[i][j]) d[i][j] = 1;
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 vis[maxn];
memset(vis, 0, sizeof(vis));
vector<int> circles[maxn];
int circlescnt = 0;
for(int i = 0; i < n; i ++) {
if(!vis[i]) {
queue<int> q;
q.push(i);
vis[i] = 1;
circles[circlescnt].push_back(i);
while(!q.empty()) {
int u = q.front(); q.pop();
for(int j = 0; j < n; j ++) if(!vis[j]){
if(d[u][j] && d[j][u]) { //in a calling circle
vis[j] = 1;
circles[circlescnt].push_back(j);
q.push(j);
}
}
}
circlescnt ++;
}
}
for(int i = 0; i < circlescnt; i ++) {
for(int j = 0; j < circles[i].size(); j ++) {
printf("%s", names[circles[i][j]].c_str());
if(j!= circles[i].size() - 1) printf(", "); else printf("\n");
}
}
}
void init() {
cnt = 0;
names.clear();
roster.clear();
memset(d, 0, sizeof(d));
memset(G, 0, sizeof(G));
}
int main() {
int T = 0;
while(scanf("%d%d", &n, &m) && n) {
init();
if(T) printf("\n");
printf("Calling circles for data set %d:\n", ++T);
string from, to;
int fromID, toID;
for(int i = 0; i < m; i ++) {
cin>>from>>to;
fromID = getID(from), toID = getID(to);
G[fromID][toID] = 1;
}
floyd();
dfs();
}
return 0;
}