• 洛谷2764 最小路径覆盖问题


    问题描述:

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

    编程任务:

    对于给定的给定有向无环图G,编程找出G的一个最小路径覆盖。

    Input Format

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

    Output Format

    从第1 行开始,每行输出一条路径(行末无空格)。文件的最后一行是最少路径数。

    网络流经典题,网络流24题之一

    题意就是在一个有向无环图里,用最少的路径数覆盖每一个点。

    就是如果i,j有一条边,就将i和j+n连一条边,跑一下最大匹配

    最少路径条数ans=n-最大匹配数

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    #define maxn 10005
    #define inf 0x7fffff
    int n,m;
    int ans;
    int cnt=1;
    int to[maxn],head[maxn],q[maxn],h[maxn];
    bool mark[maxn];
    struct edge{
        int next,to,w;
    }e[2000005];
    void ins(int u,int v,int w){
        cnt++;
        e[cnt].next=head[u];e[cnt].to=v;e[cnt].w=w;
        head[u]=cnt;
    }
    void insert(int u,int v,int w){
        ins(u,v,w);ins(v,u,0);
    }
    bool bfs(){
        int t=0,w=1;
        int now;
        memset(h,-1,sizeof h);
        q[0]=h[0]=0;
        while(t<w){
            now=q[t];t++;
            for(int i=head[now];i;i=e[i].next){
                int s=e[i].to;
                if(e[i].w&&h[s]==-1){
                    h[s]=h[now]+1;
                    q[w++]=s;
                }
            }
        }
        if(h[8001]==-1)return 0;
        return 1;
    }
    int dfs(int x,int f){
        if(x==8001)return f;
        int w,used=0;
        for(int i=head[x];i;i=e[i].next){
            int s=e[i].to;
            if(e[i].w&&h[s]==h[x]+1){
                w=f-used;
                w=dfs(s,min(w,e[i].w));
                if(w){
                    to[x]=s;
                    if(s-n>0)mark[s-n]=1;
                }
                e[i].w-=w;
                e[i^1].w+=w;
                used+=w;
                if(used==f)return f;
            }
        }
        if(!used)h[x]=-1;
        return used;
    }
    void dinic(){
        while(bfs())ans-=dfs(0,inf);
    }
    int main(){
        scanf("%d%d",&n,&m);
        int x,y;
        for(int i=1;i<=m;i++){
            scanf("%d%d",&x,&y);
            insert(x,n+y,inf);
        }
        for(int i=1;i<=n;i++)insert(0,i,1);
        for(int i=1;i<=n;i++)insert(i+n,8001,1);
        ans=n;
        dinic();
        for(int i=1;i<=n;i++){
            if(mark[i])continue;
            int k=i;
            printf("%d ",i);
            while(to[k]){
                printf("%d ",to[k]-n);
                k=to[k]-n;
            }
            printf("
    ");
        }
        printf("%d",ans);
    }
  • 相关阅读:
    2.6
    20、算法的复杂度
    SVN的部署及分支等方法
    19、数据库设计的三大范式
    2.ViewBag、ViewData、TempData之间的区别
    1、MVC和EF中的 Model First 和 Code First
    19、lambda表达式树
    12、c#中事务及回滚
    11、Linq的使用
    18、(番外)匿名方法+lambda表达式
  • 原文地址:https://www.cnblogs.com/Elfish/p/8277464.html
Copyright © 2020-2023  润新知