【uva 247】Calling Circles(图论--Floyd 传递闭包+并查集 连通分量)

题意:有N个人互相打了M次电话,请找出所有电话圈(Eg.a→b,b→c,c→d,d→a 就算一个电话圈)并输出。(N≤25,L≤25,注意输出格式)

解法:由于N比较小所有n^2或n^3的复杂度都没有问题。所以就O(n^2)读入;O(n^3)Floyd算法求出传递闭包,d[i][j]表示 i 是否直接或间接给 j 打过电话,并查集并起一个电话圈里的人;O(n^2)输出。总的是O(n^3)的时间复杂度。

P.S.我的代码有点长~再补个连通分量和强连通分量的知识:连通分量——强连通图的连通分量为其本身。如果为非连通图,则连通分量为该图的最大连通子图;有向图强连通分量——在有向图G中,如果两个顶点vi,vj间(vi>vj)有一条从vi到vj的有向路径,同时还有一条从vj到vi的有向路径,则称两个顶点强连通(strongly connected)。如果有向图G的每两个顶点都强连通,称G是一个强连通图。有向图的极大强连通子图,称为强连通分量(strongly connected components)。

 1 #include<cstdio>
 2 #include<cstdlib>
 3 #include<cstring>
 4 #include<iostream>
 5 using namespace std;
 6 
 7 const int N=27,M=910;
 8 int n,m,T=0;
 9 int d[N][N],fa[N];
10 char s[N],ss[N],str[N][N];
11 
12 void input()
13 {
14     int x,y,len=0;
15     memset(d,0,sizeof(d));
16     for (int i=1;i<=m;i++)
17     {
18       scanf("%s%s",s,ss);
19       x=y=0;
20       for (int j=1;j<=len;j++)
21       {
22         if (!strcmp(s,str[j])) x=j;
23         if (!strcmp(ss,str[j])) y=j;
24       }
25       if (!x) memcpy(str[++len],s,sizeof(s)),x=len;
26       if (!y) memcpy(str[++len],ss,sizeof(ss)),y=len;
27       d[x][y]=1;
28     }
29 }
30 int ffind(int x)
31 {
32     if (fa[x]!=x) fa[x]=ffind(fa[x]);
33     return fa[x];
34 }
35 void solve()
36 {
37     for (int k=1;k<=n;k++)
38      for (int i=1;i<=n;i++)
39       for (int j=1;j<=n;j++)
40         d[i][j]=d[i][j]|(d[i][k]&d[k][j]);
41 
42     for (int i=1;i<=n;i++) fa[i]=i;
43     for (int i=1;i<=n;i++)
44      for (int j=1;j<=n;j++)
45      {
46        if (!d[i][j] || !d[j][i]) continue;
47        int fx=ffind(i),fy=ffind(j);
48        if (fx!=fy) fa[fx]=fy;
49      }
50     if (T) printf("
");
51     printf("Calling circles for data set %d:
",++T);
52     for (int i=1;i<=n;i++)
53     {
54       if (fa[i]!=i) continue;
55       printf("%s",str[i]);
56       for (int j=1;j<=n;j++)
57         if (fa[j]==i && i!=j) printf(", %s",str[j]);
58       printf("
");
59     }
60 }
61 int main()
62 {
63     while (1)
64     {
65       scanf("%d%d",&n,&m);
66       if (!n && !m) break;
67       input();
68       solve();
69     }
70     return 0;
71 }
原文地址:https://www.cnblogs.com/konjak/p/6036091.html