「网络流24题」最小路径覆盖问题

传送门:>Here<

题意:求DAG的最小路径覆盖并输出方案。所谓最小路径覆盖是指,将原图分为若干条路径,任意两条路径不能有公共点,要使路径数量尽可能少

思路分析

依然能够联系到二分图。事实上这个问题在学二分图的时候提到过,然而当时并没有弄明白……

公式:DAG的最小路径覆盖 = 顶点数 - 最大匹配

千万不要弄混淆的是这里的最大匹配并不是指直接在DAG上做最大匹配,而是需要拆点然后搞。

具体过程如下:

原图共有N个点。将每个点$i$拆成两个点,记为$X_i$与$Y_i$,对于任意一条原图中的边$(u,v)$,连接$(X_u, Y_v)$(有向边)。很容易发现,左半部对应着每条边的起点,右半部对应着终点。然后以X为左半部,Y为右半部做二分图的最大匹配,得到答案ans,则最小路径覆盖就是N-ans。

为什么最小路径覆盖就是N-ans呢?

假设拆点建的图中一条匹配边都没有——也就意味着没有边。此时每一个顶点为一条路径,最小路径覆盖为N。

然后,在拆点建的图中增加一条匹配边,我们发现这对应着原图中的一个点融入了另一条路径,因此最小路径覆盖要-1。进一步我们发现,每增加一条能够匹配的边,就意味着原图中的又一个点加入到了某一条路径当中。因此最小路径覆盖会-1。因此有多少条匹配边就减几次。所以要让答案最小,也就是让匹配边尽量多。问题转化为了二分图的最大匹配问题

那为什么我们要拆点呢?原因在于原图是一个有向图,对于一个路径内部的点(非起点、终点),一定有一条边进入它,一条边从它出。如果直接拿原图做二分图匹配不会容许一个点有两条边的情况。而拆点以后,左侧的点仅仅作为起点,右侧的点仅仅作为终点,因此这种情况对应到每一个点依然只有一条边。如果一个点出发有两条边,对应着原图中一个点作为起点有两条边,此时由于要求最小路径覆盖,必须舍弃一条边,二分图匹配会自动舍弃另一条边。

以上是公式的原理,下面来谈如何输出方案。

对于每一个起点,我们记录它出发是否有一条饱和弧到达一个终点,如果有,意味着它一定不是终点。我们对于每一个点记录一个由它出发到达的点(sec),以及以它作为终点的边的那个起点(pre)。如果当前点不作为任何一条边的终点,那它就是起点;反之,如果不到达任何一个其他点,那么它就是终点。因此我们只需要枚举每个点以及由他延伸出去的弧,查看每条弧是否饱和,若饱和则说明这是匹配边,记录sec和pre即可

Code

/*By DennyQi*/
#include <cstdio>
#include <queue>
#include <cstring>
#include <algorithm>
#define  r  read()
#define  Max(a,b)  (((a)>(b)) ? (a) : (b))
#define  Min(a,b)  (((a)<(b)) ? (a) : (b))
using namespace std;
typedef long long ll;
const int MAXN = 10010;
const int MAXM = 10010;
const int INF = 1061109567;
inline int read(){
    int x = 0; int w = 1; register int c = getchar();
    while(c ^ ‘-‘ && (c < ‘0‘ || c > ‘9‘)) c = getchar();
    if(c == ‘-‘) w = -1, c = getchar();
    while(c >= ‘0‘ && c <= ‘9‘) x = (x << 3) +(x << 1) + c - ‘0‘, c = getchar(); return x * w;
}
int N,M,S,T,x,y,ans_min;
int first[MAXM*2],nxt[MAXM*2],to[MAXM*2],cap[MAXM*2],flow[MAXM*2],num_edge=-1;
int level[MAXN],cur[MAXN],pre[MAXN],sec[MAXN];
queue <int> q;
inline void add(int u, int v, int c, int f){
    to[++num_edge] = v;
    cap[num_edge] = c;
    flow[num_edge] = f;
    nxt[num_edge] = first[u];
    first[u] = num_edge;
}
inline bool BFS(){
    memset(level, 0, sizeof(level));
    while(!q.empty()) q.pop();
    q.push(S);
    level[S] = 1;
    int u,v;
    while(!q.empty()){
        u = q.front(); q.pop();
        for(int i = first[u]; i != -1; i = nxt[i]){
            v = to[i];
            if(!level[v] && cap[i]-flow[i]>0){
                level[v] = level[u]+1;
                q.push(v);
            }
        }
    }
    return level[T]!=0;
}
int DFS(int u, int a){
    if(u == T || a == 0) return a;
    int ans = 0, v, _f;
    for(int& i = cur[u]; i != -1; i = nxt[i]){
        v = to[i];
        if(level[u]+1==level[v] && cap[i]-flow[i]>0){
            _f = DFS(v, Min(a,cap[i]-flow[i]));
            ans += _f, a -= _f;
            flow[i] += _f, flow[i^1] -= _f;
            if(a == 0) break;
        }
    }
    return ans;
}
inline void Dinic(){
    int ans = 0;
    while(BFS()){
        for(int i = S; i <= T; ++i) cur[i] = first[i];
        ans += DFS(S, INF);
    }
    ans_min = N - ans;
}
int main(){
    N=r,M=r;
    S = 0, T = 2*N+2;
    memset(first, -1, sizeof(first));
    for(int i = 1; i <= M; ++i){
        x=r,y=r;
        add(x, y+N, 1, 0);
        add(y+N, x, 0, 0);
    }
    for(int i = 1; i <= N; ++i){
        add(S, i, 1, 0), add(i, S, 0, 0);
        add(i+N, T, 1, 0), add(T, i+N, 0, 0);
    }
    Dinic();
    for(int i = 1; i <= N; ++i){
        int v;
        for(int j = first[i]; j != -1; j = nxt[j]){
            v = to[j];
            if(cap[j]-flow[j]==0 && cap[j]==1){
                pre[v-N] = i;
                sec[i] = v-N;
            }
        }
    }
    for(int i = 1; i <= N; ++i){
        if(!pre[i]){
            int u = i;
            while(sec[u] != 0){
                printf("%d ", u);
                u = sec[u];
            }
            printf("%d\n",u);
        }
    }
    printf("%d", ans_min);
    return 0;
}

原文地址:https://www.cnblogs.com/qixingzhi/p/9418690.html

时间: 2024-11-09 10:41:45

「网络流24题」最小路径覆盖问题的相关文章

LiberOJ #6002. 「网络流 24 题」最小路径覆盖

#6002. 「网络流 24 题」最小路径覆盖 内存限制:256 MiB时间限制:1000 ms标准输入输出 题目类型:传统评测方式:Special Judge 上传者: 匿名 提交提交记录统计讨论测试数据 题目描述 给定有向图 G=(V,E) G = (V, E)G=(V,E).设 P PP 是 G GG 的一个简单路(顶点不相交)的集合.如果 V VV 中每个顶点恰好在 P PP 的一条路上,则称 P PP 是 G GG 的一个路径覆盖.P PP 中路径可以从 V VV 的任何一个顶点开始,

LibreOJ #6002. 「网络流 24 题」最小路径覆盖

内存限制:256 MiB 时间限制:1000 ms 标准输入输出 题目类型:传统 评测方式:Special Judge 上传者: 匿名 网络流 最大流 屠龙宝刀点击就送 #include <cstring> #include <cstdio> #include <queue> #define N 6005 #define inf 0x3f3f3f3f using namespace std; bool flag[N]; int n,m,dep[N],nextt[N<

网络流24题之最小路径覆盖问题

DAG的最小不相交路径覆盖 算法:把原图的每个点V拆成Vx 和Vy两个点,如果有一条有向边A->B,那么就加边Ax−>By .这样就得到了一个二分图.那么最小路径覆盖=原图的结点数-新图的最大匹配数. 证明:一开始每个点都是独立的为一条路径,总共有n条不相交路径.我们每次在二分图里找一条匹配边就相当于把两条路径合成了一条路径,也就相当于路径数减少了1.所以找到了几条匹配边,路径数就减少了多少.所以有最小路径覆盖=原图的结点数-新图的最大匹配数. 因为路径之间不能有公共点,所以加的边之间也不能有

LiberOJ 6003. 「网络流 24 题」魔术球 贪心或者最小路径覆盖

6003. 「网络流 24 题」魔术球 内存限制:256 MiB时间限制:1000 ms标准输入输出 题目类型:传统评测方式:Special Judge 上传者: 匿名 提交提交记录统计讨论测试数据 题目描述 假设有 n nn 根柱子,现要按下述规则在这 n nn 根柱子中依次放入编号为 1,2,3,4,? 1, 2, 3, 4, \cdots1,2,3,4,? 的球. 每次只能在某根柱子的最上面放球. 在同一根柱子中,任何 2 22 个相邻球的编号之和为完全平方数. 试设计一个算法,计算出在 

[loj #6003]「网络流 24 题」魔术球 二分图最小路径覆盖,网络流

#6003. 「网络流 24 题」魔术球 内存限制:256 MiB时间限制:1000 ms标准输入输出 题目类型:传统评测方式:Special Judge 上传者: 匿名 提交提交记录统计讨论测试数据 题目描述 假设有 n nn 根柱子,现要按下述规则在这 n nn 根柱子中依次放入编号为 1,2,3,4,? 1, 2, 3, 4, \cdots1,2,3,4,? 的球. 每次只能在某根柱子的最上面放球. 在同一根柱子中,任何 2 22 个相邻球的编号之和为完全平方数. 试设计一个算法,计算出在

LiberOJ #6007. 「网络流 24 题」方格取数 最小割 最大点权独立集 最大流

#6007. 「网络流 24 题」方格取数 内存限制:256 MiB时间限制:1000 ms标准输入输出 题目类型:传统评测方式:文本比较 上传者: 匿名 提交提交记录统计讨论测试数据 题目描述 在一个有 m×n m \times nm×n 个方格的棋盘中,每个方格中有一个正整数. 现要从方格中取数,使任意 2 22 个数所在方格没有公共边,且取出的数的总和最大.试设计一个满足要求的取数算法. 输入格式 文件第 1 11 行有 2 22 个正整数 m mm 和 n nn,分别表示棋盘的行数和列数

LiberOJ #6013. 「网络流 24 题」负载平衡 最小费用最大流 供应平衡问题

#6013. 「网络流 24 题」负载平衡 内存限制:256 MiB时间限制:1000 ms标准输入输出 题目类型:传统评测方式:文本比较 上传者: 匿名 提交提交记录统计讨论测试数据 题目描述 G 公司有 n nn 个沿铁路运输线环形排列的仓库,每个仓库存储的货物数量不等.如何用最少搬运量可以使 n nn 个仓库的库存数量相同.搬运货物时,只能在相邻的仓库之间搬运. 输入格式 文件的第 1 11 行中有 1 11 个正整数 n nn,表示有 n nn 个仓库.第 2 22 行中有 n nn 个

「网络流24题」 题目列表

「网络流24题」 题目列表 序号 题目标题 模型 题解 1 飞行员配对方案问题 二分图最大匹配 <1> 2 太空飞行计划问题 最大权闭合子图 <2> 3 最小路径覆盖问题 二分图最小路径覆盖 <3> 4 魔术球问题 <4> 5 圆桌问题 <5> 6 最长递增子序列问题 <6> 7 试题库问题 <7> 8 机器人路径规划问题 <8> 9 方格取数问题 二分图最大点权独立集 <9> 10 餐巾计划问题

「网络流24题」2. 太空飞行计划问题

「网络流24题」2. 太空飞行计划问题 <题目链接> 最大权闭合子图. 源点与实验连边权为实验费用的有向边: 仪器与汇点连边权为仪器费用的有向边: 实验与仪器之间连边权为INF的有向边. 答案为所有与源点相连的边的边权和减去图的最小割. 证明见国集队员胡伯涛论文<最小割模型在信息学竞赛中的应用>. 输出路径时,最后一次层次图中: 与源点相连的点即选做的实验:与汇点相连的点即选用的仪器. 注意 ·读入数据时,读到空格继续,否则停止. ·仪器部分的点权+50,避免两部点权相同. #in