大致题意:
给出一个有向图,现在要删去一个点使得剩下的图中含有点数最多的强连通分量最小。
大致思路:
枚举删点,每次求一遍强连通分量即可
#include<iostream> #include<cstdio> #include <algorithm> #include<cstring> using namespace std; const int inf=1<<30; const int nMax=3150; const int mMax=20100; class edge{ public: int v,nex; };edge e[mMax]; int k,head[nMax]; void addedge(int a,int b){ e[k].v=b; e[k].nex=head[a]; head[a]=k;k++; } int dfn[nMax],low[nMax],sta[nMax],top,atype,belon[nMax],dep,pnum[nMax]; bool insta[nMax]; void Tarjan(int u,int dnum){ int i,j; dfn[u]=low[u]=++dep; sta[++top]=u; insta[u]=1; for(i=head[u];i;i=e[i].nex){ int v=e[i].v; if(v==dnum)continue; if(!dfn[v]){ Tarjan(v,dnum); low[u]=min(low[u],low[v]); } else{ if(insta[v])low[u]=min(low[u],dfn[v]); } } if(dfn[u]==low[u]){ atype++; do{ j=sta[top--]; belon[j]=atype; pnum[atype]++; insta[j]=0; }while(u!=j); } } void init(){ // k=1; dep=1; top=atype=0; memset(pnum,0,sizeof(pnum)); memset(insta,0,sizeof(insta)); //????? // memset(head,0,sizeof(head)); //??????? memset(low,0,sizeof(low)); //Tarjan?low?? memset(dfn,0,sizeof(dfn)); //Tarjan?dfn?? memset(belon,0,sizeof(belon)); } int main(){ int i,j,m,n,a,b,ans; while(cin>>n>>m) { ans=inf; k=1; memset(head,0,sizeof(head)); for(i=0;i<m;i++){ scanf("%d%d",&a,&b); addedge(a,b); } for(int dnum=0;dnum<n;dnum++){ init(); for(i=0;i<n;i++){ if(!dfn[i]&&i!=dnum)Tarjan(i,dnum); } int maxx=0; for(i=1;i<=atype;i++){ maxx=max(pnum[i],maxx); } ans=min(maxx,ans); } if(ans==1)ans=0; cout<<ans<<endl; } return 0; }