一道多校联合赛的题,就是因为这道题才看强连通分量的,,,看了几天,现在算是明白了。。。具体到这道题,求出强连通分量的个数后,再统计出度为0的强连通分量的个数和入度为0的强连通分量的个数,取较大值即可。。。。。。。题目:
4 0 3 2 1 2 1 3
4 2HintCase 2: First prove set 2 is a subset of set 1 and then prove set 3 is a subset of set 1.
#include <iostream> #include <string.h> #include <cstdio> #include <vector> using namespace std; int n,m,index,cnt,top; const int N=20010; int in[N],out[N],dfn[N],low[N]; int stack[N],belong[N]; bool instack[N]; vector<int> ss[N]; void init(){ index=cnt=top=0; memset(ss,0,sizeof(ss)); memset(dfn,0,sizeof(dfn)); memset(low,0,sizeof(low)); memset(belong,0,sizeof(belong)); memset(stack,0,sizeof(stack)); memset(instack,0,sizeof(instack)); memset(in,0,sizeof(in)); memset(out,0,sizeof(out)); } int min(int x,int y){ if(x>y) return y; else return x; } int max(int x,int y){ if(x>y) return x; else return y; } void targin(int x){ dfn[x]=low[x]=++index; instack[x]=true; stack[++top]=x; int j; for(int i=0;i<ss[x].size();++i){ if(dfn[ss[x][i]]==0){ targin(ss[x][i]); low[x]=min(low[ss[x][i]],low[x]); } else if(instack[ss[x][i]]){ low[x]=min(low[x],dfn[ss[x][i]]); } } if(low[x]==dfn[x]){ cnt++; do{ j=stack[top--]; belong[j]=cnt; instack[j]=false; }while(x!=j); } } int main(){ while(~scanf("%d%d",&n,&m)){ if(m==0) printf("%d\n",n); else{ init(); int x,y; while(m--){ scanf("%d%d",&x,&y); ss[x].push_back(y); } for(int i=1;i<=n;++i){ if(dfn[i]==0) targin(i); } if(cnt==1) printf("0\n"); else{ for(int i=1;i<=n;++i){ for(int j=0;j<ss[i].size();++j){ int x=belong[i]; int y=belong[ss[i][j]]; if(x!=y) { out[x]=1;in[y]=1; } } } int xx=0,yy=0; for(int i=1;i<=cnt;++i){ if(!in[i]) xx++; if(!out[i]) yy++; } printf("%d\n",max(xx,yy)); } } } return 0; }