poj2186--tarjan+縮點


題目大意:

      每一頭牛的願望就是變成一頭最受歡迎的牛。現在有N頭牛,給你M對整數(A,B),表示牛A認為牛B受歡迎。 這
種關系是具有傳遞性的,如果A認為B受歡迎,B認為C受歡迎,那么牛A也認為牛C受歡迎。你的任務是求出有多少頭
牛被所有的牛認為是受歡迎的。
 
      先用tarjan求出每個強連通分量,再縮點,統計每個點的出度,如果有且只有1個出度為0的點,就輸出這個點包含的節點數,否則輸出0.
 
證明:
      如果有強連通分量被孤立(即和其他強連通分量無邊相連),那么答案一定是0,此時由於縮點后是一個DAG圖,出度為0的點的個數一定大於1.
      如果沒有點被孤立,當出度為0的點多於1個時,由DAG圖的性質可得,一定不存在一個點能從其他所有點到達。只有當出度為0的點的個數等於1時,這個出度為0的點才能被其他所有點到達。
#include<iostream>
#include<cstdio>
#include<vector>
#include<string.h>
#include<cmath>
using namespace std;
vector<int>g[10010];
int n,m,x,y,i,j,v,c[10010],l=0,low[10010],dfn[10010],f[10010],cnt=0,out0[10010],sum[10010],time_clock=0;
void tarjan(int u){
    low[u]=dfn[u]=++time_clock;
    c[++l]=u;
    for(int i=0;i<g[u].size();++i){
        v=g[u][i];
        if(!dfn[v]){
            tarjan(v);
            low[u]=min(low[u],low[v]);
        }else if(!f[v])low[u]=min(low[u],dfn[v]);
    }
    if(low[u]==dfn[u]){
        int len=l;
        cnt++;
        while(c[l]!=u)f[c[l--]]=cnt;
        f[c[l--]]=cnt;
        sum[cnt]=len-l;
    }
}
int main()
{
    scanf("%d%d",&n,&m);
    for(i=1;i<=m;++i){
        scanf("%d%d",&x,&y);
        g[x].push_back(y);
    }
    memset(dfn,0,sizeof(dfn));
    for(i=1;i<=n;++i)if(!dfn[i])tarjan(i);
    for(i=1;i<=n;++i)
    for(j=0;j<g[i].size();++j){
        v=g[i][j];
        if(f[i]!=f[v])out0[f[i]]++;
    }
    x=0;
    for(i=1;i<=cnt;++i)
    if(!out0[i]){
        if(x>0){
            printf("0");
            return 0;
        }
        x=sum[i];
    }
    printf("%d",x);
    return 0;
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM