tarjan算法--cojs 1298. 通讯问题



cojs 1298. 通讯问题

★   输入文件:jdltt.in   输出文件:jdltt.out   简单对比
时间限制:1 s   内存限制:128 MB

【题目描述】

一个篮球队有n个篮球队员,每个队员都有联系方式(如电话、电子邮件等)。但并不是每个队员的联系方式都公开,每个队员的联系方式只有一部分队员知道。问队员可以分成多少个小组,小组成员之间可以相互通知(包括一个队员一个组,表示自己通知自己)。

【输入格式】

输入文件有若干行

第一行,一个整数n,表示共有n个队员(2<=n<=100)下面有若干行,每行2个数a、b,a、b是队员编号,表示a知道b的通讯方式。

【输出格式】

输出文件有若干行

第一行,1个整数m,表示可以分m个小组,下面有m行,每行有若干个整数,表示该小组成员编号,输出顺序按编号由小到大。

【样例输入】

12
1 3
2 1
2 4
3 2
3 4
3 5
4 6 
5 4
6 4
7 4
7 8
7 12
8 7
8 9
10 9
11 10

【样例输出】

8

1 2 3

4 6

5

7 8

9

10

11

12

  1 /*先进行tarjan把所有的强连通分量放到几个数组中去,然后先对每个数组中的元素按字典序排序,然后把几个数组按照字典序排序,这样才能按照题目的意思输出*/
  2 #include<iostream>
  3 using namespace std;
  4 #include<cstring>
  5 #include<cstdio>
  6 #include<stack>
  7 stack<int>sta;
  8 #include<algorithm>
  9 #define N 120
 10 int dfn[N],low[N];
 11 int n,anst=0;
 12 struct Ans{
 13     int a[N];
 14     void sor(){sort(a+1,a+a[0]+1);}
 15 }ans[N];
 16 struct Edge{
 17     int v,last;
 18 }edge[N*N*2];
 19 int topt=0,t=0;
 20 int head[N];
 21 bool visited[N]={0},instack[N]={0};
 22 void add_edge(int u,int v)
 23 {
 24     ++t;
 25     edge[t].v=v;
 26     edge[t].last=head[u];
 27     head[u]=t;
 28 }
 29 void input()
 30 {
 31     scanf("%d",&n);
 32     int u,v;
 33     while(scanf("%d%d",&u,&v)==2)
 34     {
 35         add_edge(u,v);
 36     }
 37 }
 38 void tarjan(int k)/*tarjan算法,不解释*/
 39 {
 40     visited[k]=true;
 41     dfn[k]=low[k]=++topt;
 42     sta.push(k);
 43     instack[k]=true;
 44     for(int l=head[k];l;l=edge[l].last)
 45     {
 46         if(!visited[edge[l].v])
 47         {
 48             tarjan(edge[l].v);
 49             low[k]=min(low[k],low[edge[l].v]);  
 50         }
 51         else {
 52             if(instack[edge[l].v])
 53               low[k]=min(low[k],dfn[edge[l].v]);
 54         }
 55         
 56     }
 57     if(low[k]==dfn[k])
 58     {
 59         anst++;
 60         int ys=sta.top();
 61         instack[ys]=false;
 62         sta.pop();
 63         while(ys!=k)
 64         {
 65             ans[anst].a[0]++;
 66             ans[anst].a[ans[anst].a[0]]=ys;
 67             ys=sta.top();
 68             instack[ys]=false;
 69             sta.pop();
 70         }
 71         instack[ys]=false;
 72         ans[anst].a[0]++;
 73         ans[anst].a[ans[anst].a[0]]=ys;
 74     }
 75 }
 76 int cmp(Ans p,Ans q)
 77 {
 78     for(int i=1;i<=p.a[0]&&i<=q.a[0];++i)
 79     {
 80         if(p.a[i]<q.a[i])
 81           return true;
 82     }
 83     return false;
 84 }
 85 int main()
 86 {
 87     freopen("jdltt.in ","r",stdin);
 88     freopen("jdltt.out","w",stdout);
 89     input();
 90     for(int i=1;i<=n;++i)
 91       if(!visited[i])
 92         tarjan(i);
 93     for(int i=1;i<=anst;++i)
 94        ans[i].sor();/*对每个强连通分量的元素排序,注意结构体函数的妙用*/
 95     sort(ans+1,ans+anst+1,cmp);/*再把所有的强连通分量排序*/
 96     printf("%d
",anst);
 97     for(int i=1;i<=anst;++i)
 98     {
 99         for(int j=1;j<=ans[i].a[0];++j)
100           printf("%d ",ans[i].a[j]);
101         printf("
");
102     }
103     fclose(stdin);fclose(stdout);
104     return 0;
105 }

 

原文地址:https://www.cnblogs.com/c1299401227/p/5492902.html