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

     

    题目描述

    对于一个路径覆盖会有两个性质:

    1.每个点属于且只属于一条路径;

    2.在每条路径中,除终点外,每个点只有一条边可以通向路径中的另外一个点。

    所以可以把每个点拆成两个点,一个是起始点,一个是目标点,建立二分图模型。

    二分图中的任何一种匹配都对应着一种路径覆盖方案。

    若匹配数为零,那么路径数=总点数,每增加一个匹配,就会减少一条路径,所以有

            最小路径覆盖数=总点数-最大匹配数

    再在匹配过程中记录路径最后输出即可。

    #include<complex>
    #include<cstdio>
    using namespace std;
    const int INF=0x3f3f3f3f;
    const int N=401,M=6007;
    struct node{
        int v,f,nxt;
    }e[M<<1];
    int n,m,Enum=1,s,t,ans;
    int front[N],cur[N],deep[N],path[N];
    int q[N];
    bool vis[N];
    int qread()
    {
        int x=0;
        char ch=getchar();
        while(ch<'0' || ch>'9')ch=getchar();
        while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return x;
    }
    void Insert(int u,int v)
    {
        e[++Enum].v=v;e[Enum].f=1;e[Enum].nxt=front[u];front[u]=Enum;
        e[++Enum].v=u;e[Enum].nxt=front[v];front[v]=Enum;
    }
    bool bfs()
    {
        for(int i=0;i<=t;i++)
        {
            deep[i]=0;
            cur[i]=front[i];
        }
        int head=1,tail=0,u,v;
        deep[s]=1;q[++tail]=s;
        while(head<=tail)
        {
            u=q[head++];
            for(int i=front[u];i;i=e[i].nxt)
            {
                v=e[i].v;
                if(!deep[v] && e[i].f)
                {
                    deep[v]=deep[u]+1;
                    if(v==t)return 1;
                    q[++tail]=v;
                }
            }
        }
        return 0;
    }
    int dfs(int x,int cur_flow)
    {
        if(x==t)return cur_flow;
        int rest=cur_flow,v;
        for(int &i=cur[x];i;i=e[i].nxt)
        {
            v=e[i].v;
            if(deep[v]==deep[x]+1 && e[i].f && rest)
            {
                int new_flow=dfs(v,min(e[i].f,rest));
                e[i].f-=new_flow;
                e[i^1].f+=new_flow;
                rest-=new_flow;
                if(new_flow)path[x]=v-n;
                if(!rest)return cur_flow;
            }
        }
        deep[x]=0;
        return cur_flow-rest;
    }
    void Dinic()
    {
        while(bfs())
            ans+=dfs(s,INF);
    }
    void print(int x)
    {
        if(!x)return;
        printf("%d ",x);
        vis[x]=1;
        print(path[x]);
    }
    int main()
    {
        scanf("%d%d",&n,&m);
        s=0;t=n+n+1;
        int u,v;
        for(int i=1;i<=m;i++)
        {
            u=qread();v=qread();
            Insert(u,v+n);
        }
        for(int i=1;i<=n;i++)
        {
            Insert(s,i);
            Insert(i+n,t);
        }
        Dinic();
        for(int i=1;i<=n;i++)
            if(!vis[i])
            {
                print(i);
                puts("");
            }
        printf("%d
    ",n-ans);
        return 0;
    }
  • 相关阅读:
    svn cleanup failed–previous operation has not finished 解决方法
    开源SNS社区系统推荐
    从网络获取图片本地保存
    MS SQL Server 数据库连接字符串
    KeepAlive
    Configure Git in debian
    sqlserver query time
    RPi Text to Speech (Speech Synthesis)
    SQL Joins with C# LINQ
    search or reseed identity columns in sqlserver 2008
  • 原文地址:https://www.cnblogs.com/LeTri/p/8757649.html
Copyright © 2011-2022 走看看