最长反链=最小链覆盖

参考vfk dalao的博客:http://vfleaking.blog.163.com/blog/static/1748076342012918105514527/

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<iostream>
#include<string>
#include<ctime>
#include<queue>
#include<map>
#include<set>
#include<vector>
typedef long long LL;
using namespace std;
const int N=411,inf=1e9;
int Write[20];
struct edge{int to,nxt,v;}e[48010];
int n,m,head[N],cnt,pre[N],ans,p[N],w[N],d[N],has[N],S,T;
bool a[N][N];
int read() {int d=0,f=1; char c=getchar(); while (c<'0'||c>'9') {if (c=='-') f=-1; c=getchar();} while (c>='0'&&c<='9') d=(d<<3)+(d<<1)+c-48,c=getchar(); return d*f;}
void write(int x){int t=0; for (;x;x/=10) Write[++t]=x%10; if (!t) putchar('0'); for (int i=t;i>=1;i--) putchar((char)(Write[i]+48));}
void judge(){freopen(".in","r",stdin); freopen(".out","w",stdout);}
void addedge(int x,int y,int z)
{
    e[++cnt]=(edge){y,head[x],z}; head[x]=cnt;
    e[++cnt]=(edge){x,head[y],0}; head[y]=cnt;
}
void floyd()
{
    for (int k=1;k<=n;k++)
        for (int i=1;i<=n;i++)
            for (int j=1;j<=n;j++)
                a[i][j]|=(a[i][k]&&a[k][j]);
}
int sap()
{
    int flow=inf,x=S,res=0;
    has[0]=T+1;
    for (int i=S;i<=T;i++) p[i]=head[i];
    while (d[S]<T+1)
    {
        w[x]=flow; bool flag=0;
        for (int i=p[x];i;i=e[i].nxt)
        {
            int y=e[i].to;
            if (e[i].v==0||d[y]+1!=d[x]) continue;
            p[x]=i; flag=1;
            flow=min(flow,e[i].v);
            x=y; pre[x]=i;
            if (x==T)
            {
                res+=flow;
                while (x!=S)
                {
                    int k=pre[x];
                    e[k].v-=flow;
                    e[k^1].v+=flow;
                    x=e[k^1].to;
                }
                flow=inf;
            }
            break;
        }
        if (flag) continue;
        int ljj,pjy=T;
        for (int i=head[x];i;i=e[i].nxt)
        {
            int y=e[i].to;
            if (e[i].v&&d[y]<pjy) pjy=d[y],ljj=i;
        }
        if (--has[d[x]]==0) break;
        p[x]=ljj;
        has[d[x]=pjy+1]++;
        if (x!=S) x=e[pre[x]^1].to,flow=w[x];
    }
    return res;
}
int main()
{
    //judge();
    n=read(); m=read(); S=0; T=2*n+1;
    for (int i=1;i<=m;i++)
    {
        int x=read(),y=read();
        a[x][y]=1;
    }
    floyd();
    cnt=1;
    for (int i=1;i<=n;i++) addedge(S,i,1),addedge(i+n,T,1);
    for (int i=1;i<=n;i++)
        for (int j=1;j<=n;j++)
            if (a[i][j]) addedge(i,j+n,inf);
    write(n-sap());
    return 0;
}
View Code