bzoj1093: [ZJOI2007]最大半连通子图
认真想一想这个半联通子图缩完点以后其实就是一条链
topsort里面记录下即可
注意缩完点后会有重边,要判掉
#include<cstdio> #include<iostream> #include<cstring> #include<cstdlib> #include<algorithm> #include<cmath> #include<map> using namespace std; int mod; struct node { int x,y,next; }a[2100000];int len,last[110000]; void ins(int x,int y) { len++; a[len].x=x;a[len].y=y; a[len].next=last[x];last[x]=len; } int z,dfn[110000],low[110000]; int top,sta[110000];bool v[110000]; int cnt,belong[110000],tot[110000]; void SCC(int x) { dfn[x]=low[x]=++z; sta[++top]=x;v[x]=true; for(int k=last[x];k;k=a[k].next) { int y=a[k].y; if(dfn[y]==0) { SCC(y); low[x]=min(low[x],low[y]); } else if(v[y]==true) low[x]=min(low[x],dfn[y]); } if(dfn[x]==low[x]) { int i;cnt++; do { i=sta[top];top--; v[i]=false; belong[i]=cnt; tot[cnt]++; }while(i!=x); } } node e[2100000];int elen,elast[110000]; void eins(int x,int y) { elen++; e[elen].x=x;e[elen].y=y; e[elen].next=elast[x];elast[x]=elen; } map<int,bool>mp[110000]; int du[110000]; void composition() { elen=0;memset(elast,0,sizeof(elast)); memset(du,0,sizeof(du)); for(int i=1;i<=len;i++) if(belong[a[i].x]!=belong[a[i].y]&&mp[belong[a[i].x]][belong[a[i].y]]==false) { mp[belong[a[i].x]][belong[a[i].y]]=true; eins(belong[a[i].x],belong[a[i].y]); du[belong[a[i].y]]++; } } int f[110000],g[110000]; int main() { freopen("a.in","r",stdin); freopen("a.out","w",stdout); int n,m,x,y; scanf("%d%d%d",&n,&m,&mod); len=0;memset(last,0,sizeof(last)); for(int i=1;i<=m;i++) { scanf("%d%d",&x,&y); ins(x,y); } z=top=cnt=0; memset(dfn,0,sizeof(dfn)); memset(low,0,sizeof(low)); memset(v,false,sizeof(v)); memset(tot,0,sizeof(tot)); for(int i=1;i<=n;i++) if(dfn[i]==0)SCC(i); composition(); top=0; memset(f,0,sizeof(f)); memset(g,0,sizeof(g)); for(int i=1;i<=cnt;i++) if(du[i]==0)sta[++top]=i,f[i]=tot[i],g[i]=1; while(top!=0) { int x=sta[top];top--; for(int k=elast[x];k;k=e[k].next) { int y=e[k].y; if(f[y]<f[x]+tot[y]) { f[y]=f[x]+tot[y]; g[y]=g[x]; } else if(f[y]==f[x]+tot[y]) g[y]=(g[x]+g[y])%mod; du[y]--;if(du[y]==0)sta[++top]=y; } } int ans=0,sum=0; for(int i=1;i<=n;i++) if(f[i]>ans)ans=f[i],sum=g[i]; else if(f[i]==ans)sum=(sum+g[i])%mod; printf("%d\n%d\n",ans,sum); return 0; }
pain and happy in the cruel world.