tarjan算法+缩点:求强连通分量 POJ 2186

Posted tech-chen

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了tarjan算法+缩点:求强连通分量 POJ 2186相关的知识,希望对你有一定的参考价值。

强连通分量:1309. [HAOI2006]受欢迎的牛

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

【题目描述】

每一头牛的愿望就是变成一头最受欢迎的牛。现在有N头牛,给你M对整数(A,B),表示牛 A 认为牛

B受欢迎。这种关系是具有传递性的,如果A认为B受欢迎,B认为C受欢迎,那么牛A也认为牛C受欢迎。你的任务是求出有多少头牛被所有的牛认为是受欢迎的。

【输入格式】

第1行两个整数N,M;

   接下来M行,每行两个数A,B,意思是A认为B是受欢迎的(给出的信息有可能重复,即有可能出现多个A,B)

【输出格式】

一个数,即有多少头牛被所有的牛认为是受欢迎的。

【样例输入】

3 3
1 2
2 1
2 3

【样例输出】

1

【数据范围】

10%的数据N<=20,M<=50

30%的数据N<=1000,M<=20000

70%的数据N<=5000,M<=50000

100%的数据N<=10000,M<=50000

  1 /*判断能不能有“牛被所有的牛认为是受欢迎”,那就是缩点之后的图中出度为0的点只有一个,如果图中出度为0的点有多个,肯定不符合情况,找出该点之后,再输出该强连通分量即可*/
  2 #include<iostream>
  3 using namespace std;
  4 #include<cstdio>
  5 #include<cstring>
  6 #include<stack>
  7 #define N 10010
  8 #define M 50010
  9 bool in_stack[N];
 10 int low[N],dfn[N],x,y,n,m,father[N];
 11 int chudu[N],t=0,topt=0,head[N];
 12 struct Edge{
 13     int v,last,u;
 14 }edge[M*2];
 15 stack<int>sta;
 16 int ans[N],begi,en;
 17 int read()
 18 {
 19     int sum=0,ff=1;
 20     char s;
 21     s=getchar();
 22     while(s<0||s>9)
 23     {
 24         if(s==-) ff=-1;
 25         s=getchar();
 26     }
 27     while(s>=0&&s<=9)
 28     {
 29         sum=sum*10+s-0;
 30         s=getchar();
 31     }
 32     return sum*ff;
 33 }
 34 void add_edge(int u,int v,int k)
 35 {
 36     edge[k].u=u;
 37     edge[k].v=v;
 38     edge[k].last=head[u];
 39     head[u]=k;
 40 }
 41 void input()
 42 {
 43     n=read();m=read();
 44     for(int i=1;i<=m;++i)
 45     {
 46         x=read();y=read();
 47         add_edge(x,y,i);
 48     }
 49 }
 50 void tarjan(int u)
 51 {
 52     low[u]=dfn[u]=++topt;
 53     sta.push(u);
 54     in_stack[u]=true;
 55     for(int l=head[u];l;l=edge[l].last)
 56     {
 57         int v=edge[l].v;
 58         if(!dfn[v])
 59         {
 60             tarjan(v);
 61             low[u]=min(low[u],low[v]);
 62         }
 63         else if(in_stack[v])
 64              low[u]=min(low[u],dfn[v]);
 65     }
 66     if(low[u]==dfn[u])
 67     {
 68         ans[++ans[0]]=u;
 69         int x;
 70         do
 71         {
 72             x=sta.top();
 73             sta.pop();
 74             in_stack[x]=false;
 75             father[x]=u;
 76         }while(x!=u);
 77     }
 78 }
 79 void suo_dian()
 80 {
 81     for(int l=1;l<=m;++l)
 82     {
 83         if(father[edge[l].v]!=father[edge[l].u])
 84         {
 85             chudu[father[edge[l].u]]++;
 86         }
 87     }
 88 }
 89 int main()
 90 {
 91     freopen("cow.in","r",stdin);
 92     freopen("cow.out","w",stdout);
 93     input();
 94     for(int i=1;i<=n;++i)
 95     {
 96         if(!dfn[i])
 97         {
 98             tarjan(i);
 99         }
100     }
101     suo_dian();
102     int sum=0,l;
103     for(int i=1;i<=ans[0];++i)
104       if(chudu[ans[i]]==0)
105       {
106           sum++;
107           l=ans[i];
108       }
109     if(sum>1) printf("0");
110     else if(sum==1)
111     {
112         sum=0;
113         for(int i=1;i<=n;++i)
114           if(father[i]==l)
115           sum++;
116         printf("%d\n",sum);
117     }
118     fclose(stdin);fclose(stdout);
119     return 0;
120 }

 

以上是关于tarjan算法+缩点:求强连通分量 POJ 2186的主要内容,如果未能解决你的问题,请参考以下文章

POJ-3180 The Cow Prom(tarjan求强连通分量)

缩点(tarjan求强连通分量)

图论算法-Tarjan模板 缩点;割顶;双连通分量

BZOJ10511051: [HAOI2006]受欢迎的牛 tarjan求强连通分量+缩点

P3387 模板缩点(Tarjan求强连通分量)

原创tarjan算法初步(强连通子图缩点)