poj2186【利用强连通分量】

题意:
有n头奶牛,然后有个规则是A->B,B->C,那么A->C;
A觉得B受欢迎,B觉得C受欢迎,那么A觉得C受欢迎;
求:被其他所有牛都欢迎的牛的数量;
思路:
原来的思路:
我们只要在缩点之后的图中,找出出度为0的点,然后输出它里面的点就可以了。【虽然AC了】
然后我觉得这样不是会有缺陷么?他可能入度也为0呢?也就是缩点后那个出度为0点是独立的。所以还是要判断入度吧。
后来其实没必要入度,我们继续查看其他出度为0的点,如果存在的话那肯定是有独立的部分,然后如果没有的话,嘿嘿,那么肯定就是他了。
总结:
利用tarjan算法可以办到缩点。
然后主要的思路就是:在一张图里面,经过缩点后,出度为0的点只有一个的话,那么他肯定被其他点在一定程度上给盯上了。
—————————————歌:飞得更高–汪峰

//#include <bits/stdc++.h>
#include<iostream>
#include<cstdio>
#include<math.h>
#include<string.h>
#include<algorithm>
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
const double eps=1e-6;
const double pi=acos(-1.0);
const int mod=998244353;
const int INF=0x3f3f3f3f;

const int N=1e4+8;

struct asd{
    int to;
    int next;
};
asd q[N*5];
int head[N*5],tol;

int n;
int dfn[N];
int low[N];
int st[N],vis[N],in[N];
int p,tp,sum;
int kr[N];
int xx[N];

void INIT()
{
    tol=0;
    memset(head,-1,sizeof(head));
}
void add(int a,int b)
{
    q[tol].to=b;
    q[tol].next=head[a];
    head[a]=tol++;
}

void tarjan(int u)
{
    dfn[u]=low[u]=++p;
    st[++tp]=u;
    vis[u]=1;
    for(int i=head[u];i!=-1;i=q[i].next)
    {
        int x=q[i].to;
        if(!dfn[x]){
            tarjan(x);
            low[u]=min(low[u],low[x]);
        }
        else if(vis[x]){
            low[u]=min(low[u],dfn[x]);
        }
    }
    if(dfn[u]==low[u]){
        int temp;
        sum++;
        while(1){
            temp=st[tp];
            in[temp]=sum;
            vis[temp]=0;
            tp--;
            if(temp==u){
                break;
            }
        }
    }
}


void solve()
{
    memset(kr,0,sizeof(kr));
    memset(xx,0,sizeof(xx));
    for(int i=1;i<=n;i++){
        for(int v=head[i];v!=-1;v=q[v].next){
            int t=q[v].to;
            if(in[t]!=in[i]){
                kr[in[i]]++;
            }
        }
    }
    int ans=0,num=0,k;
    for(int i=1;i<=sum;i++){
        if(!kr[i]){
            num+=1;
            k=i;
        }
    }
    if(num==1){
        for(int i=1;i<=n;i++)
        {
            if(in[i]==k){
                ans++;
            }
        }
        printf("%d
",ans);
    }
    else{
        puts("0");
    }
}

int main()
{
    int a,b,m;
    scanf("%d%d",&n,&m);
    INIT();
    while(m--){
        scanf("%d%d",&a,&b);
        add(a,b);
    }
    tp=p=sum=0;
    memset(vis,0,sizeof(vis));
    memset(low,0,sizeof(low));
    for(int i=1;i<=n;i++)
    {
        if(!dfn[i]){
            tarjan(i);
        }
    }
    solve();
    return 0;
}
原文地址:https://www.cnblogs.com/keyboarder-zsq/p/5934428.html