洛谷要求输出方案,懒得写了,但是还是放一下链接看看吧
(虽然现在二分图已经过气了=。=)
要求最长反链,最长反链=最小链覆盖,先Floyd传递闭包之后链覆盖就变成了边覆盖,然后最小边覆盖=总点数-最大匹配
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 const int N=300,M=100000,inf=1e9; 6 int n,m,s,f,b,t,t1,t2,t3,cnt,ans; 7 int noww[2*M],goal[2*M],flow[2*M]; 8 int p[N],pp[N],dep[N],que[N],lnk[N][N]; 9 void Link(int f,int t,int v) 10 { 11 noww[++cnt]=p[f],p[f]=cnt; 12 goal[cnt]=t,flow[cnt]=v; 13 noww[++cnt]=p[t],p[t]=cnt; 14 goal[cnt]=f,flow[cnt]=0; 15 } 16 bool Layering(int st,int ed) 17 { 18 for(int i=1;i<=t;i++) pp[i]=p[i]; 19 memset(dep,-1,sizeof dep); 20 dep[st]=0,que[f=b=0]=st; 21 while(f<=b) 22 { 23 int tn=que[f++]; 24 for(int i=pp[tn];i;i=noww[i]) 25 if(dep[goal[i]]==-1&&flow[i]) 26 dep[goal[i]]=dep[tn]+1,que[++b]=goal[i]; 27 } 28 return ~dep[ed]; 29 } 30 int Augmenting(int nd,int ed,int mn) 31 { 32 if(nd==ed||!mn) return mn; 33 int tmp=0,tep=0; 34 for(int i=pp[nd];i;i=noww[i]) 35 { 36 pp[nd]=i; 37 if(dep[goal[i]]==dep[nd]+1) 38 if(tep=Augmenting(goal[i],ed,min(mn,flow[i]))) 39 { 40 flow[i]-=tep,mn-=tep; 41 flow[i^1]+=tep,tmp+=tep; 42 if(!mn) break; 43 } 44 } 45 return tmp; 46 } 47 void Dinic_Maxflow(int st,int ed) 48 { 49 while(Layering(st,ed)) 50 ans+=Augmenting(st,ed,inf); 51 } 52 int main() 53 { 54 scanf("%d%d",&n,&m),s=2*n+1,t=s+1,cnt=1; 55 for(int i=1;i<=m;i++) 56 scanf("%d%d",&t1,&t2),lnk[t1][t2]=true; 57 for(int k=1;k<=n;k++) 58 for(int i=1;i<=n;i++) 59 for(int j=1;j<=n;j++) 60 lnk[i][j]|=lnk[i][k]&lnk[k][j]; 61 for(int i=1;i<=n;i++) 62 for(int j=1;j<=n;j++) 63 if(lnk[i][j]) Link(i,j+n,1); 64 for(int i=1;i<=n;i++) 65 Link(s,i,1),Link(i+n,t,1); 66 Dinic_Maxflow(s,t),printf("%d",n-ans); 67 return 0; 68 }