1. 程式人生 > 實用技巧 >P2341 [USACO03FALL][HAOI2006]受歡迎的牛 G

P2341 [USACO03FALL][HAOI2006]受歡迎的牛 G

P2341 [USACO03FALL][HAOI2006]受歡迎的牛 G:

題目描述:

輸入格式:

輸出格式:

輸入輸出樣例:

輸入 #1

3 3
1 2
2 1
2 3

輸出 #1

 1

說明/提示:

資料範圍:

分析:

這道題明顯的是tarjan,但是隻知道tarjan是解不了的,我們分析可以的到最受歡迎的牛隻可能是強聯通分量中的出度為零的點,只有一個,假如有兩個出度為零的點,那麼就會形成兩個SCC,進而沒有牛會受到所有的奶牛的喜歡,進而就不會存在明星奶牛,所以我們統計所有點的出度,如果出度大於1,直接輸出0,結束就可以了,然後再找那一個出度為0的點,輸出他的sum值就行,sum存這一個SCC中的點數量。

Code:

#include<bits/stdc++.h>
using namespace std;
const int N=5e4+10;
int n,m,x,y;
int sta[N],head[N],dfn[N],low[N];
int top,tot,Time,cnt,g[N],sum[N];
bool vis[N];
int cd[N];
struct edge{
    int to;
    int ne;
}e[N];

void add(int u,int v){
    e[++cnt].to = v;
    e[cnt].ne = head[u];
    head[u] 
= cnt; } void tarjan(int u){ dfn[u]=low[u]=++Time; vis[u]=1;sta[++top]=u; for(int i=head[u];i;i=e[i].ne){ int v = e[i].to; if(!dfn[v]){ tarjan(v); low[u] = min( low[u] , low[v]); } if(vis[v]){ low[u] = min(low[u] , dfn[v]); } }
if(dfn[u] == low[u]){ tot++; while(sta[top+1]!=u){ int v = sta[top--]; vis[v] = 0; g[v] = tot; sum[tot]++; } } } int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=m;i++){ 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=e[j].ne){ int v = e[j].to; if(g[i]!=g[v]){ cd[g[i]]++; } } } int pos=0; for(int i=1;i<=tot;i++){ if(!cd[i]){ if(pos){ printf("0\n"); return 0; } pos=i; } } printf("%d\n",sum[pos]); return 0; }