1. 程式人生 > >計蒜客習題:受歡迎的蒜頭

計蒜客習題:受歡迎的蒜頭

問題描述

蒜廠除了蒜頭君還有很多小蒜頭。
每隻蒜頭的夢想是成為最受歡迎的蒜頭。有 N 只蒜頭,有 M 對二元關係 (A,B),告訴你蒜頭 A 認為蒜頭 B 是受歡迎的。如果 A 認為 B 是受歡迎的,B 認為 C 是受歡迎的,則 A 也認為 C 是受歡迎的。你的任務是計算被其餘蒜頭都認為是受歡迎的蒜頭數量。
輸入格式
第一行兩個正整數 N 和 M,分別表示一共有 N 只小蒜頭和 M 對二元關係(1≤N≤10000,1≤M≤50000)。
接下來 M 行,每行兩個整數 A 和 B,表示 A 認為 B 是受歡迎的 (1≤A,B≤N)。
輸出格式
一行一個整數,表示答案。
樣例輸入
4 6
1 2
1 3
1 4
2 3
2 4
3 4
樣例輸出


1

AC程式碼

#include <cstdio>  
#include <iostream>  
#include <cstring>  
#include <queue>  
#include <stack>  
#include <vector>  


using namespace std;    
const int maxn=2e5+10;    
vector<int>v[maxn];//鄰接表,存原圖    
vector<int>scc[maxn];//縮點後的圖    
stack
<int>
s; int dfn[maxn],low[maxn],tot,ins[maxn]; //dfn是否為0可以判斷點是否訪問過,ins陣列用來判斷點是否在棧中 //dfn陣列表示頂點dfs的時間戳,low[]為u能夠追溯到的最早的棧中頂點的次序號 int scc_cnt;//強聯通分量的個數 int sccnum[maxn];//縮點陣列,表示某個點對應的縮點值,即縮完點之後的下標 int in[maxn],out[maxn];//出度入度 int n,m; void readin()//因為初始化問題,莫名其妙的wa,真的醉 { int
x,y; tot=0; scc_cnt=0; fill(ins,ins+maxn,0); fill(sccnum,sccnum+maxn,0); fill(dfn,dfn+maxn,0);fill(low,low+maxn,0); fill(in,in+maxn,0); fill(out,out+maxn,0); scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) v[i].clear(),scc[i].clear(); while(!s.empty()) s.pop(); for(int i=1;i<=m;i++){ scanf("%d%d",&x,&y); v[x].push_back(y); } } void tarjan(int x) { low[x]=dfn[x]=++tot;// s.push(x);ins[x]=1; for(int i=0;i<v[x].size();i++){ int p=v[x][i]; if(!dfn[p]){//判斷點是否被訪問過 tarjan(p); low[x]=min(low[x],low[p]); } else if(ins[p]) low[x]=min(low[x],dfn[p]);//判斷點是否在棧中 } if(low[x]==dfn[x]){//dfs到葉子節點,開始判斷,如果==就到達了某個強聯通分量的根節點,dfs回溯到了這個點 scc_cnt++; scc[scc_cnt].clear(); while(1){//得出某個強聯通分量的集合 int now=s.top(); s.pop(); ins[x]=0;//出棧ins置0 if(sccnum[now]!=scc_cnt) scc[scc_cnt].push_back(x); sccnum[now]=scc_cnt;//將該連通分量中的每個點都賦予相同的值 if(now==x) break;//通過棧找到那個點 } } } int main() { readin(); for(int i=1;i<=n;i++){ if(!dfn[i]){ tarjan(i); } } //出度入度的統計方法 for(int u=1;u<=n;u++){ for(int i=0;i<v[u].size();i++){ int uu=v[u][i]; if(sccnum[u]!=sccnum[uu]){ in[sccnum[uu]]++; out[sccnum[u]]++; } } } int ansp=-1; int flag=-1; for(int i=1;i<=scc_cnt;i++){ if(out[i]==0){ flag++; ansp=i; } } if(flag==0) cout<<scc[ansp].size()<<endl; else cout<<"0"<<endl; }