Time Limit: 2000MS | Memory Limit: 65536K | |
Descriptionnode
Inputide
Outputthis
Sample Inputspa
3 3 1 2 2 1 2 3
Sample Outputcode
1
Hintorm
Sourceblog
#include <cstdio> #include <cstring> #include <cstdlib> #include <cmath> #include <queue> #include <stack> #include <vector> #include <algorithm> using namespace std; const int Max = 10100; typedef struct node { int v; int next; }Line; vector<int>G[Max]; Line Li[Max*5]; int Head[Max],top; int dfn[Max],low[Max],pre[Max]; int num[Max],Num,Du[Max]; int dep; bool vis[Max]; int ans; stack<int>S; void AddEdge(int u,int v) { Li[top].v=v ; Li[top].next=Head[u]; Head[u]=top++; } void Tarjan(int u)// Tarjan求強連通份量 { dfn[u]=low[u]=dep++; S.push(u); for(int i=Head[u];i!=-1;i=Li[i].next) { if(dfn[Li[i].v]==-1) { Tarjan(Li[i].v); low[u]=min(low[u],low[Li[i].v]); } else { low[u]=min(low[u],dfn[Li[i].v]); } } if(low[u]==dfn[u])//強連通份量的根節點 { while(!S.empty()) { int v = S.top(); S.pop(); pre[v] = Num;//給份量集合標號 G[Num].push_back(v);//記錄集合對應的點 num[Num]++; if(v==u) { break; } } Num++; } } int main() { int n,m; while(~scanf("%d %d",&n,&m)) { top = 0; memset(Head,-1,sizeof(Head)); int u,v; for(int i=0;i<m;i++) { scanf("%d %d",&u,&v); AddEdge(u,v); } memset(dfn,-1,sizeof(dfn)); memset(num,0,sizeof(num)); for(int i =0;i<=n;i++) { G[i].clear(); } dep = 0;Num = 0; for(int i=1;i<=n;i++) { if(dfn[i]==-1) { Tarjan(i); } } memset(Du,0,sizeof(Du)); for(int i=0; i<Num ;i++) //判斷強連通份量的出度 { memset(vis,false,sizeof(vis)); for(int k=0;k<G[i].size();k++) { for(int j=Head[G[i][k]]; j!=-1;j=Li[j].next) { if(i!=pre[Li[j].v]) { if(!vis[pre[Li[i].v]])//因爲不一樣的強連通份量之間相連的邊可能不止一條,因此要判斷是否是已經統計過。 { vis[pre[Li[i].v]]=true; Du[i]++; } } } } } ans = 0; int ant = 0; for(int i=0;i<Num;i++)//若是超過一個的出度爲零的強連通份量,則這些連通份量就不能被其餘的牛都仰慕。 { if(Du[i]==0) { ans+=num[i]; ant++; } } printf("%d\n",ant<=1?ans:0); } return 0; }