1. 程式人生 > >Luogu P2341 [HAOI2006]受歡迎的牛 SCC縮點

Luogu P2341 [HAOI2006]受歡迎的牛 SCC縮點

etc names 一個 sig lin 連通 include ostream tmp

把強連通分量縮點,如果有且僅有一個出度為0的強連通分量,那麽答案就是他的size;如果有多個入度為0的,那麽沒有明星牛。

#include<cstdio>
#include<iostream>
#define R register int
using namespace std;
inline int g() {
    R ret=0; register char ch; while(!isdigit(ch=getchar())); 
    do ret=ret*10+(ch^48); while(isdigit(ch=getchar())); return
ret; } int n,m,cc,cnt,num,top,ans; int vr[50010],nxt[50010],fir[10010],dfn[10010],low[10010],stk[10010],c[10010],sz[10010],r[10010]; bool vis[10010]; inline void add(int u,int v) {vr[++cnt]=v,nxt[cnt]=fir[u],fir[u]=cnt;} void tarjan(int u) { dfn[u]=low[u]=++num; stk[++top]=u,vis[u]=true; for(R i=fir[u];i;i=nxt[i]) { R v=vr[i];
if(!dfn[v]) { tarjan(v); low[u]=min(low[u],low[v]); } else if(vis[v]) low[u]=min(low[u],dfn[v]); } if(dfn[u]==low[u]) { R tmp; ++cc; do tmp=stk[top],vis[tmp]=false,c[tmp]=cc,++sz[cc],--top; while(tmp!=u); } } inline void solve() { R tot=0
; for(R u=1;u<=n;++u) for(R i=fir[u];i;i=nxt[i]) { R v=vr[i]; if(c[u]!=c[v]) ++r[c[u]];} for(R i=1;i<=cc;++i) if(!r[i]&&++tot>1) {ans=0; break; } else if(!r[i]) ans=sz[i]; printf("%d\n",ans); } signed main() { n=g(),m=g(); for(R i=1,u,v;i<=m;++i) u=g(),v=g(),add(u,v); for(R i=1;i<=n;++i) if(!dfn[i]) tarjan(i); solve(); }

2019.04.18

Luogu P2341 [HAOI2006]受歡迎的牛 SCC縮點