洛谷P2341 [USACO03NOV][HAOI2006]受欢迎的牛 G 强连通分量

题目链接:https://www.luogu.com.cn/problem/P2341

本题就是要求强连通分量,那么何为强连通分量?言简意赅地说就是在一个有向图中所有点可以互相可达。在一个强连通分量中,所有牛都是互相喜欢的。我们可以用tarjan来求强连通分量,把一个强连通分量的点全部染成一个颜色,如果一个强连通分量的出度为0,这个强连通分量的牛就可能是明星奶牛,但如果有两个强连通分量的出度为0,那就不可能有明星奶牛。因为如果这种情况出现的话,就肯定所有奶牛不被至少一个奶牛崇拜,所以不可能有明星奶牛。
代码如下

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e4+5;
const int maxm=5e4+5;
struct node
{
    int to,next;
}p[maxm];
int dfn[maxn],low[maxn],stc[maxn];
int col[maxn],col_num[maxn],head[maxn];
int outdeg[maxn];
bool vis[maxn];
int top,cnt,dfn_num,col_id;
void add(int x,int y)
{
    p[++cnt].next=head[x];
    p[cnt].to=y;
    head[x]=cnt;
}
void tarjan(int u)
{
     stc[++top]=u;
     vis[u]=1;
     dfn[u]=low[u]=++dfn_num;
     for(int i=head[u];i;i=p[i].next)
     {
         int v=p[i].to;
         if(!dfn[v])
         {
            tarjan(v);
            low[u]=min(low[u],low[v]);
         }
         else if(vis[v])
         low[u]=min(low[u],dfn[v]);
     }
     if(dfn[u]==low[u])
     {
         vis[u]=false;
         col[u]=++col_id;
         int len=1;
         while(stc[top]!=u)
         {
             len++;
             vis[stc[top]]=false;
             col[stc[top--]]=col_id;
         }
         col_num[col_id]=len;
         top--;
     }
}
int n,m;
int main()
{
    scanf("%d %d",&n,&m);
    for(int i=1;i<=m;i++)
    {
        int x,y;
        scanf("%d %d",&x,&y);
        add(x,y);
    }
    for(int i=1;i<=n;i++)
    if(!dfn[i])
    tarjan(i);
    for(int i=1;i<=n;i++)
    for(int j=head[i];j;j=p[j].next)
    {
        int v=p[j].to;
        if(col[v]!=col[i])//不是一个强连通分量
        outdeg[col[i]]++;
    }
    int ans=0;
    for(int i=1;i<=col_id;i++)
    if(!outdeg[i])
    {
        if(ans)//两个出度为0,没有明星奶牛
        {
            puts("0");
            return 0;
        }
        else
        ans=col_num[i];
    }
    printf("%d\n",ans);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_44491423/article/details/104552001