
洛谷要求输出方案,懒得写了,但是还是放一下链接看看吧
(虽然现在二分图已经过气了=。=)
要求最长反链,最长反链=最小链覆盖,先Floyd传递闭包之后链覆盖就变成了边覆盖,然后最小边覆盖=总点数-最大匹配
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=,M=,inf=1e9;
int n,m,s,f,b,t,t1,t2,t3,cnt,ans;
int noww[*M],goal[*M],flow[*M];
int p[N],pp[N],dep[N],que[N],lnk[N][N];
void Link(int f,int t,int v)
{
noww[++cnt]=p[f],p[f]=cnt;
goal[cnt]=t,flow[cnt]=v;
noww[++cnt]=p[t],p[t]=cnt;
goal[cnt]=f,flow[cnt]=;
}
bool Layering(int st,int ed)
{
for(int i=;i<=t;i++) pp[i]=p[i];
memset(dep,-,sizeof dep);
dep[st]=,que[f=b=]=st;
while(f<=b)
{
int tn=que[f++];
for(int i=pp[tn];i;i=noww[i])
if(dep[goal[i]]==-&&flow[i])
dep[goal[i]]=dep[tn]+,que[++b]=goal[i];
}
return ~dep[ed];
}
int Augmenting(int nd,int ed,int mn)
{
if(nd==ed||!mn) return mn;
int tmp=,tep=;
for(int i=pp[nd];i;i=noww[i])
{
pp[nd]=i;
if(dep[goal[i]]==dep[nd]+)
if(tep=Augmenting(goal[i],ed,min(mn,flow[i])))
{
flow[i]-=tep,mn-=tep;
flow[i^]+=tep,tmp+=tep;
if(!mn) break;
}
}
return tmp;
}
void Dinic_Maxflow(int st,int ed)
{
while(Layering(st,ed))
ans+=Augmenting(st,ed,inf);
}
int main()
{
scanf("%d%d",&n,&m),s=*n+,t=s+,cnt=;
for(int i=;i<=m;i++)
scanf("%d%d",&t1,&t2),lnk[t1][t2]=true;
for(int k=;k<=n;k++)
for(int i=;i<=n;i++)
for(int j=;j<=n;j++)
lnk[i][j]|=lnk[i][k]&lnk[k][j];
for(int i=;i<=n;i++)
for(int j=;j<=n;j++)
if(lnk[i][j]) Link(i,j+n,);
for(int i=;i<=n;i++)
Link(s,i,),Link(i+n,t,);
Dinic_Maxflow(s,t),printf("%d",n-ans);
return ;
}