洛谷 2341 tarjan缩点

题目传送门:https://www.luogu.org/problemnew/show/P2341#sub

这道题有一个想法很重要,就是成为超级明星的奶牛所在的强连通分量出度为0,假如出度不为0,而他又有入度,那你不是把强连通分量求错了吗。但是假如有两个以上出度为0的奶牛群,那就会发生这几个奶牛群互不喜欢,遗憾的没有了超级明星,所以我们先用tarjan缩点,然后统计出度为0的点即可。附上代码:

#include<stdio.h>
#include<stdlib.h>
int head[500001]={0},low[500001]={0},co[500001]={0},to[500001]={0},x[500001]={0},y[500001]={0};
int d[500001]={0},dfn[500001]={0},nxt[500001]={0},num1[500001]={0},s[500001]={0},d2[500001]={0};
int n,m,tmp=0,top=0,col=0,num=0;
int min(int x,int y)
{
    if(x>y)
      return y;
    else return x;
}
int add(int x,int y)
{
    tmp++;
    to[tmp]=y;
    nxt[tmp]=head[x];
    head[x]=tmp;
    return 0;
}
int tarjan(int x)
{
    int i,t;
    num++;top++;
    s[top]=x;
    low[x]=num;dfn[x]=num;
    for(i=head[x];i;i=nxt[i])
      {
      t=to[i];
      if(dfn[t]==0)
        {
        tarjan(t);
        low[x]=min(low[x],low[t]);
        }
      else if(co[t]==0)
        {
        low[x]=min(low[x],dfn[t]);
        }
      }
    if(dfn[x]==low[x])
      {
      col++;
      co[x]=col;
      d[col]++;
      while(s[top]!=x)
        {
        co[s[top]]=col;
        d[col]++;//统计每个强连通分量里有几头奶牛
        top--;
        }
      top--;
      }
    return 0;
}
int main()
{
    int i,tmp,j,flag=0;
    scanf("%d%d",&n,&m);
    for(i=1;i<=m;i++)
      {
      scanf("%d%d",&x[i],&y[i]);
      add(x[i],y[i]);
      }
    for(i=1;i<=n;i++)
      if(dfn[i]==0)
        tarjan(i);
    for(i=1;i<=n;i++)
      for(j=head[i];j;j=nxt[j])
        if(co[i]!=co[to[j]])
          d2[co[i]]++;//统计出度
    for(i=1;i<=col;i++)
      if(d2[i]==0&&flag==0)
        {
        tmp=d[i];flag=1;
        }
      else if(d2[i]==0&&flag==1)
        {
        printf("0");
        return 0;
        }
    printf("%d",tmp);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_40892508/article/details/82718853