题目好长好啰嗦。。。其实是水题一道,就是找出结点数大于1的强连通分量的个数。此处用tarjan实现。
以下是代码:
#include<cstdio>#include<cstring>#include<iostream>using namespace std;const int N=30000;const int M=70000;struct node{ int u,v; int next;}edge[M];int head[N],num;int cnt[N],dep[N],Bcnt,dindex,low[N],stack[N],top;bool instack[N];int n,m;void init(){ int i; for(i=0;i<=n+3;i++) { head[i]=-1; cnt[i]=0; } num=0;}void addege(int u,int v){ edge[num].u=u; edge[num].v=v; edge[num].next=head[u]; head[u]=num++;}void tarjan(int i){ int j,v; dep[i]=low[i]=++dindex; instack[i]=true; stack[++top]=i; for(j=head[i];j!=-1;j=edge[j].next) { v=edge[j].v; if(!dep[v]) { tarjan(v); if(low[v]<low[i]) low[i]=low[v]; } else if(instack[i] && dep[v]<low[i]) low[i]=dep[v]; } if(dep[i]==low[i]) { Bcnt++; do { j=stack[top--]; instack[j]=false; cnt[Bcnt]++; }while(j!=i); }}void solve(){ int i; top=Bcnt=dindex=0; memset(dep,0,sizeof(dep)); memset(instack,0,sizeof(instack)); for(i=1;i<=n;i++) if(!dep[i]) { tarjan(i); }}int main(){ scanf("%d%d",&n,&m); init(); int i; for(i=1;i<=m;i++) { int a,b; scanf("%d%d",&a,&b); addege(a,b); } solve(); int cout=0; for(i=1;i<=Bcnt;i++) if(cnt[i]>=2) cout++; printf("%d/n",cout); return 0;}