zoukankan      html  css  js  c++  java
  • [网络流24题] 最小路径覆盖问题

    Link:

    P2764 传送门

    Solution:

    基本模型

    首先结论为:将每个点$v$拆成$v,v'$,有向边$edge(u,v)$改为$edge(u,v')$,建成二分图

    那么$最小路径覆盖数=n-二分图最大匹配数$

    证明:匹配$(u,v')$相当于连接了$(u,v)$,连通块个数减一,想要连通块最少自然要最大匹配

    如果要输出方案的话增广时记录$u$的下一个点$v$即可

    Code:

    #include <bits/stdc++.h>
    
    using namespace std;
    const int MAXN=2e4+10;
    struct edge{int nxt,to;}e[MAXN<<2];
    int n,m,x,y,res,vis[MAXN],mat[MAXN],nxt[MAXN],head[MAXN],in[MAXN],tot;
    
    void add_edge(int from,int to)
    {
        e[++tot]={head[from],to};head[from]=tot;
        e[++tot]={head[to],from};head[to]=tot;
    }
    
    int dfs(int x)
    {
        for(int i=head[x];i;i=e[i].nxt)
            if(!vis[e[i].to])
            {
                vis[e[i].to]=1;
                if(!mat[e[i].to]||dfs(mat[e[i].to]))
                {mat[e[i].to]=x;nxt[x]=e[i].to-n;return true;}
            }
        return false;
    }
    
    int main()
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=m;i++)
            scanf("%d%d",&x,&y),add_edge(x,n+y);
        for(int i=1;i<=n;i++)
            memset(vis,0,sizeof(vis)),res+=dfs(i);
        for(int i=1;i<=n;i++) in[nxt[i]]++;
        for(int i=1;i<=n;i++)
            if(!in[i])
            {
                for(int j=i;j;j=nxt[j])
                    printf("%d ",j);
                puts("");
            }
        printf("%d",n-res);
        return 0;
    }
  • 相关阅读:
    命令行选项
    损坏的RAID5
    Codeforces Round #600 (Div. 2)
    python 数据分析
    xor or and 线段树
    CCPC哈尔滨E题
    二维偏序
    Codeforces Round #592 (Div. 2)
    Codeforces Round #597 (Div. 2)
    pycharm 安装激活
  • 原文地址:https://www.cnblogs.com/newera/p/9544624.html
Copyright © 2011-2022 走看看