• [BZOJ]1143: [CTSC2008]祭祀river


    题目大意:给定一个n个点m条边的有向无环图,问最多选多少个点使得两两之间互不到达。(n<=100,m<=1000)

    思路:题目所求即最长反链,最长反链=最小链覆盖,对每个点向自己能到的所有点连边后,转化成最小路径覆盖,每个点拆成入点和出点后二分图匹配,又有最大二分图匹配=最小路径覆盖,问题得到解决。复杂度O(nm+MaxFlow(n,n^2))。

    #include<cstdio>
    #include<cstring>
    inline int read()
    {
        int x;char c;
        while((c=getchar())<'0'||c>'9');
        for(x=c-'0';(c=getchar())>='0'&&c<='9';)x=(x<<3)+(x<<1)+c-'0';
        return x;
    }
    #define MN 100
    #define MM 1000
    #define MV 200
    #define ME 10000
    #define S MV+1
    #define T MV+2
    #define INF 0x7FFFFFFF
    namespace MaxFlow
    {
        struct edge{int nx,t,w;}e[ME*2+5];
        int h[MV+5],en=1,d[MV+5],q[MV+5],qn,c[MV+5];
        inline void ins(int x,int y,int w)
        {
            e[++en]=(edge){h[x],y,w};h[x]=en;
            e[++en]=(edge){h[y],x,0};h[y]=en;
        }
        bool bfs()
        {
            int i,j;
            memset(d,0,sizeof(d));
            for(d[q[i=qn=0]=S]=1;i<=qn;++i)for(j=c[q[i]]=h[q[i]];j;j=e[j].nx)
                if(e[j].w&&!d[e[j].t])d[q[++qn]=e[j].t]=d[q[i]]+1;
            return d[T];
        }
        int dfs(int x,int r)
        {
            if(x==T)return r;
            int k,u=0;
            for(int&i=c[x];i;i=e[i].nx)if(e[i].w&&d[e[i].t]==d[x]+1)
            {
                k=dfs(e[i].t,r-u<e[i].w?r-u:e[i].w);
                u+=k;e[i].w-=k;e[i^1].w+=k;
                if(u==r)return r;
            }
            return d[x]=0,u;
        }
        int dinic(){int ans=0;while(bfs())ans+=dfs(S,INF);return ans;}
    };
    struct edge{int nx,t;}e[MM+5];
    int h[MN+5],en,q[MN+5],qn,u[MN+5];
    inline void ins(int x,int y){e[++en]=(edge){h[x],y};h[x]=en;}
    int main()
    {
        int n,m,i,j,k,x,y;
        n=read();m=read();
        while(m--)x=read(),y=read(),ins(x,y);
        using MaxFlow::ins;
        for(i=1;i<=n;++i)
        {
            ins(S,i,1);ins(i+n,T,1);
            memset(u,0,sizeof(u));
            for(u[q[j=qn=0]=i]=1;j<=qn;++j)for(k=h[q[j]];k;k=e[k].nx)
                if(!u[e[k].t])ins(i,e[k].t+n,INF),u[q[++qn]=e[k].t]=1;
        }
        printf("%d",n-MaxFlow::dinic());
    }
  • 相关阅读:
    Auto.js实现自动刷视频,点赞脚本(一)
    C# 将excel文件导入到SqlServer数据库
    JavaScript实现HTML导航栏下拉菜单[悬浮显示]
    补码的知识
    指针06 零基础入门学习C语言46
    指针05 零基础入门学习C语言45
    标志寄存器01 零基础入门学习汇编语言54
    标志寄存器02 零基础入门学习汇编语言55
    标志寄存器02 零基础入门学习汇编语言55
    标志寄存器01 零基础入门学习汇编语言54
  • 原文地址:https://www.cnblogs.com/ditoly/p/BZOJ1143.html
Copyright © 2020-2023  润新知