zoukankan      html  css  js  c++  java
  • 网络流24题-最小路径覆盖 (最小路径覆盖)

    题目:

    给定有向图G=(V,E)。设P是G的一个简单路(顶点不相交)的集合。如果V中每个顶点恰好在P的一条路上,则称P是G的一个路径覆盖。P中路径可以从V的任何一个顶点开始,长度也是任意的,特别地,可以为0。G的最小路径覆盖是G的所含路径条数最少的路径覆盖。

    设计一个有效算法求一个有向无环图G的最小路径覆盖。

    输入格式:

    第1行有2个正整数n和m。n是给定有向无环图G的顶点数,m是G的边数。
    接下来的m行,每行有2个正整数i 和j,表示一条有向边(i,j)。

    输出格式:

    从第一行开始,每行输出1条路径,文件的最后一行是最小路径数。

    链接: https://loj.ac/problem/6002

    思路:

    我们将每个点拆成ii+n,因为顶点不相交,那么这个图就成了一个二分图

    最小路径覆盖=顶点数-二分图最大匹配

    证明:我们先把每个顶点看成一条单独的路径,花费记为1,假设一开始有11个点,那么总花费是11,此时如果有一条边连接了1和2,即1和2匹配,那么总花费变成10

    所以要想用最小的路径覆盖所有顶点,那么要求出这个二分图中的最大匹配,用顶点总数减去二分图最大匹配即为答案。跑一遍最大流来求二分图的最大匹配。

    然后输出路径的方法是:如果这条边上的流量为0,那么说明经过了这条路径,再以这个点为起点继续寻找,跑一遍dfs即可

    代码:

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <vector>
    using namespace std;
    const int MAXN=2e5+5;
    const int INF=0x7fffffff;
    typedef long long ll;
    int head[MAXN],tot,visit[MAXN];
    int s,t,n,m;
    struct node
    {
        int to,nxt,flow;
    }e[MAXN];
    void add(int x,int y,int z)
    {
        e[tot].to=y;e[tot].nxt=head[x];e[tot].flow=z;head[x]=tot++;
    }
    void add_edge(int x,int y,int z)
    {
        add(x,y,z);add(y,x,0);
    }
    int deep[MAXN],l,r,q[MAXN];
    bool bfs()
    {
        memset(deep,0,sizeof(deep));
        l=0,r=0;
        deep[s]=1;q[++r]=s;
        while(l!=r)
        {
            int u=q[++l];
            for(int i=head[u];~i;i=e[i].nxt)
            {
                int v=e[i].to;
                if(!deep[v]&&e[i].flow)
                {
                    deep[v]=deep[u]+1;
                    q[++r]=v;
                }
            }
        }
        return deep[t];
    }
    int dfs(int u,int min_f)
    {
        if(u==t)return min_f;
        int temp_f=0;
        for(int i=head[u];~i&&min_f;i=e[i].nxt)
        {
            int v=e[i].to;
            if(deep[v]==deep[u]+1&&e[i].flow)
            {
                int d=dfs(v,min(min_f,e[i].flow));
                if(d>0)
                {
                    min_f-=d;
                    temp_f+=d;
                    e[i].flow-=d;
                    e[i^1].flow+=d;
                }
            }
        }
        if(!temp_f)deep[u]=-1;
        return temp_f;
    }
    int dinic()
    {
        int res=0;
        while(bfs())
            res+=dfs(s,INF);
        return res;
    }
    vector<int>path;
    void print(int u)
    {
        if(visit[u])return;
        visit[u]=1;
        path.push_back(u);
        for(int i=head[u];~i;i=e[i].nxt)
        {
            int v=e[i].to;
            if(e[i].flow==0&&v>n&&v<=2*n&&!visit[v])
                print(v-n);
        }
    }
    int main()
    {
        scanf("%d%d",&n,&m);
        memset(head,-1,sizeof(head));
        s=0,t=2*n+2;
        for(int i=1;i<=n;i++)
            add_edge(s,i,1);
        for(int i=n+1;i<=2*n;i++)
            add_edge(i,t,1);
        for(int i=1;i<=m;i++)         //注意这里连边的时候要将x与y拆分出来的那个点相连
        {
            int x,y;scanf("%d%d",&x,&y);
            add_edge(x,y+n,1);
        }
        int ans=dinic();
        for(int i=1;i<=n;i++)
        {
            print(i);
            if(path.size())     //输出路径
            {
                for(int i=0;i<path.size();i++)
                    printf("%d%c",path[i],i==path.size()-1?'
    ':' ');
                path.clear();
            }
        }
        printf("%d
    ",n-ans);
        return 0;
    }
  • 相关阅读:
    VS Code 中文显示乱码_ubuntu
    解决source insight不识别.cu文件的问题/sourceinsight设置.cu类型的文件
    PPT图片素材
    Jetson Xavier NX apt更换国内源
    xavier NX安装torchvision
    xavier NX上安装pytorch_前面一二三四是失败的方法,可以直接按照步骤五进行安装
    jquery.cookie()方法
    JavaScript错误处理
    Jquery中$.post()与$.get()区别
    jQuery中$.get()、$.post()和$.ajax()
  • 原文地址:https://www.cnblogs.com/ljxdtc666/p/12377108.html
Copyright © 2011-2022 走看看