题解 P2863 【[USACO06JAN]牛的舞会The Cow Prom】
赤裸裸的板子,就加一个特判就行。直接上代码
#include<stdio.h> #include<algorithm> #include<iostream> using namespace std; bool ins[10000000];//记录入没入栈。 bool typ[10000000];//特判*1,是强连通分量就直接过了。 int top;int ans[10000000]; int stack[10000000];//手写栈。 void push(int x)//手写栈ing. { ins[x]=true; stack[++top]=x; return ; } void pop() { ins[stack[top]]=false; top--; return ; } struct data{ int v;int next; }edge[10000000]; int cnt;int alist[10000000]; void add(int u,int v)//继续手写结构体。 { edge[++cnt].v=v; edge[cnt].next=alist[u]; alist[u]=cnt; } int dfn[100000];int dfu;//dfn作为x的入栈序号。 int low[1000000];int res=0; void dfs(int x)//dfs { dfn[x]=++dfu;//记录搜索序号 push (x); low[x]=dfn[x]; int next=alist[x]; while(next) { int v=edge[next].v; if(ins[v]==true)//被搜过就不用再搜了 { low[x]=min(low[x],low[v]); } else if(ins[v]==false) { dfs(v); low[x]=min(low[x],low[v]); } next=edge[next].next; } if(dfn[x]==low[x])//如果搜回来了。 { while(low[stack[top]]==low[x]) { typ[stack[top]]=true; pop(); ans[x]++; } if(ans[x]>1) res++;//想要转圈的话必须要两个人及以上。 } return; } int n,m; int main() { scanf("%d%d",&n,&m); for(int i=1;i<=m;i++) { int n1,m1; scanf("%d%d",&n1,&m1);//不解释。 add(n1,m1); } for(int i=1;i<=n;i++) { if(typ[i]==1) continue;//要是在扫过的强连通分量里面直接过。 else dfs(i); } printf("%d",res); return 0;//程序拜拜 }