传递闭包。
利用c[a][b] = c[b][a] = 1; 判断是否在一个圈内~
输出结果时再新建个图,对在一个圈内的连线,输出每个连通分量即可。
#include <cstdio>
#include <cstring>
#include <vector>
#include <map>
#include <set>
#include <iostream>
using namespace std;
const int MAXN = 25 + 3;
int n, m, k;
map<string, int> IDcache;
vector<string> Setcache;
vector<int> g[MAXN];
vector<int> print_g[MAXN];
int connect[MAXN][MAXN];
int vis[MAXN];
int get_id(char *A){
if(IDcache.count(A)) return IDcache[A];
Setcache.push_back(A); return IDcache[A] = Setcache.size() - 1;
}
void reset(){
for(int i = 0; i < MAXN; i++) g[i].clear(), print_g[i].clear(); k = 0; Setcache.clear(); IDcache.clear();
for(int i = 0; i < MAXN; i++)
for(int j = 0; j < MAXN; j++)
connect[i][j] = (i == j ? 1 : 0);
}
void floyd(){
for(int u = 0; u < n; u++)
for(int v = 0; v < g[u].size(); v++)
connect[u][g[u][v]] = 1;
for(int i = 0; i < n; i++)
for(int u = 0; u < n; u++)
for(int v = 0; v < n; v++)
connect[u][v] = connect[u][v] || (connect[u][i] && connect[i][v]);
}
void print_ans(int depth, int u){
if(vis[u]) return;
if(depth) printf(", "); cout << Setcache[u];
vis[u] = 1;
for(int v = 0; v < print_g[u].size(); v++){
if(vis[print_g[u][v]]) continue;
print_ans(depth + 1, print_g[u][v]);
}
}
void solve()
{
floyd();
for(int u = 0; u < n; u++){
for(int v = 0; v < n; v++){
if(connect[u][v] && connect[v][u]) print_g[u].push_back(v), print_g[v].push_back(u);
}
}
memset(vis, 0, sizeof(vis));
for(int i = 0; i < n; i++){
if(print_g[i].size() && !vis[i]) print_ans(0, i), printf("\n");
}
}
bool init()
{
if(scanf("%d%d", &n, &m) != 2 || !(n + m)) return false; reset();
for(int i = 0; i < m; i++){
char u[MAXN], v[MAXN]; scanf("%s%s", u, v); int a, b; a = get_id(u), b = get_id(v);
g[a].push_back(b);
}return true;
}
int main(void)
{
int times = 1;
while(init()){
if(times - 1) printf("\n");
printf("Calling circles for data set %d:\n", times++), solve();
}
return 0;
}