訊息擴散[Tarjan]
阿新 • • 發佈:2018-12-02
縮點過後入度為0的就必須選
#include<bits/stdc++.h> #define N 100050 #define M 500050 using namespace std; int first[N],next[M],to[M],tot,top,sign,cnt,ans; int n,m,dfn[N],low[N],id[N],sta[N],insta[N],du[N]; void add(int x,int y){ next[++tot]=first[x],first[x]=tot,to[tot]=y; } void dfs(int u){ dfn[u]=low[u]=++sign; sta[++top]=u,insta[u]=1; for(int i=first[u];i;i=next[i]){ int t=to[i]; if(!dfn[t]) dfs(t),low[u]=min(low[u],low[t]); else if(insta[t] && dfn[t]<low[u]) low[u]=dfn[t]; } if(low[u]==dfn[u]){ cnt++; do{ id[sta[top]]=cnt,insta[sta[top]]=0; }while(sta[top--]!=u); } } int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=m;i++){ int x,y; scanf("%d%d",&x,&y); add(x,y); } for(int i=1;i<=n;i++) if(!dfn[i]) dfs(i); for(int i=1;i<=n;i++) for(int j=first[i];j;j=next[j]){ int t=to[j]; if(id[t]!=id[i]) du[id[t]]++; } for(int i=1;i<=cnt;i++) if(!du[i]) ans++; printf("%d",ans); return 0; }