bzoj1051: [HAOI2006]受欢迎的牛
tarjan缩点。网上的代码都没有缩点是把vis变成另外一个值,我也不知道是为什么。
#include<cstdio> #include<algorithm> #include<cstring> using namespace std; const int maxn = 200000 + 10; const int maxm = 1000000 + 10; int g[maxn],v[maxm],next[maxm],eid; int n,m,cid=0,vid=0,sp=0,res; int dfn[maxn],low[maxn],vis[maxn]; int s[maxn],size[maxn],color[maxn],out[maxn]; void addedge(int a,int b) { v[eid]=b; next[eid]=g[a]; g[a]=eid++; } void build() { memset(g,-1,sizeof(g)); scanf("%d%d",&n,&m); for(int i=1,a,b;i<=m;i++) { scanf("%d%d",&a,&b); addedge(a,b); } } void tarjan(int u) { vis[u]=1; s[++sp]=u; dfn[u]=low[u]=++vid; for(int i=g[u];~i;i=next[i]) { if(vis[v[i]]==0) { tarjan(v[i]); low[u]=min(low[u],low[v[i]]); } else if(vis[v[i]]==1) low[u]=min(low[u],dfn[v[i]]); } if(dfn[u]==low[u]) { ++cid; do { color[s[sp]]=cid; size[cid]++; vis[s[sp]]=2; } while(s[sp--]!=u); } } void solve() { for(int i=1;i<=n;i++) if(!vis[i]) tarjan(i); res=-1; for(int u=1;u<=n;u++) for(int i=g[u];~i;i=next[i]) if(color[u]!=color[v[i]]) out[color[u]]++; for(int i=1;i<=cid;i++) if(out[i]==0) { if(res==-1) res=size[i]; else { res=0; break; } } printf("%d\n",res); } int main() { build(); solve(); return 0; }