【网络流24题 #03】最小路径覆盖问题

题目链接:最小路径覆盖问题

哇 卡在输出也是醉了

重要结论:最小路径覆盖数 = 结点数(拆成边之前) -  最大流

本题也是点拆边

与【网络流24题 #04】魔术球问题

有异曲同工之妙

void output(int x){
    if(x >= S) return ;
    printf("%d ", x >> 1);
    for(int i = head[x]; i != -1; i = edge[i].next)
        if(!edge[i].w && edge[i].v < S) output(edge[i].v - 1);
}   

……

 for(int i = 1; i <= n; i++) fa[i] = i;
    for(int i = 0; i <= esize; i += 2) {
        if(!edge[i].w && edge[i].v < S && edge[i].u < S){
            fa[find(edge[i].v >> 1)] = find(edge[i].u >> 1);
        }
    }
    for(int i = 1; i <= n; i++){
        if(find(i) == i){
            output(i << 1);
            printf("\n");
        }

内心戏:(╯‵□′)╯︵┻━┻

悄咪咪:居然还打扰H神吃饭…

  1 #include <cstdio>
  2 #include <algorithm>
  3 #include <queue>
  4 #include <cstring>
  5 #include <cmath>
  6 using namespace std;
  7 const int N = 4e4 + 5;
  8 const int inf = 0x3f3f3f3f;
  9 int n, m;
 10 struct Edge{
 11     int u, v, w, next;
 12 }edge[N << 1];
 13 int head[N], esize = -1;
 14 bool vis[N];
 15 int next[N], fa[N];
 16 inline void addedge(int x, int y, int z){
 17     edge[++esize] = (Edge){x, y, z, head[x]};
 18     head[x] = esize;
 19     edge[++esize] = (Edge){y, x, 0, head[y]};
 20     head[y] = esize;
 21 }
 22 queue<int> q;
 23 int dep[N];
 24 int S, T;
 25
 26 bool bfs(){
 27     int fro;
 28     q.push(S);
 29     memset(dep, 0, sizeof(dep));
 30     dep[S] = 1;
 31     while(!q.empty()){
 32         fro = q.front(); q.pop();
 33         for(int i = head[fro]; i != -1; i = edge[i].next){
 34             int vv = edge[i].v;
 35             if(!dep[vv] && edge[i].w > 0){
 36                 dep[vv] = dep[fro] + 1;
 37                 q.push(vv);
 38             }
 39         }
 40     }
 41     return dep[T];
 42 }
 43
 44 int dfs(int x, int rest){
 45     if(x == T || !rest) return rest;
 46     for(int i = head[x], vv, ww, d; i != -1; i = edge[i].next){
 47         vv = edge[i].v, ww = edge[i].w;
 48         if(dep[vv] != dep[x] + 1) continue;
 49         d = dfs(vv, min(rest, ww));
 50         if(d > 0){
 51             edge[i].w -= d;
 52             edge[i ^ 1].w += d;
 53             return d;
 54         }
 55     }
 56     return 0;
 57 }
 58
 59 int dinic(){
 60     int ret = 0;
 61     while(bfs()){
 62         ret += dfs(S, inf);
 63     }
 64     return ret;
 65 }
 66
 67 int find(int x){
 68     return x == fa[x] ? x : fa[x] = find(fa[x]);
 69 }
 70
 71 void output(int x){
 72     if(x >= S) return ;
 73     printf("%d ", x >> 1);
 74     for(int i = head[x]; i != -1; i = edge[i].next)
 75         if(!edge[i].w && edge[i].v < S) output(edge[i].v - 1);
 76 }
 77
 78 int main(){
 79     scanf("%d%d", &n, &m);
 80     memset(head, -1, sizeof(head));
 81     memset(next, -1, sizeof(next));
 82     S = N - 3, T = N - 2;
 83     for(int i = 1; i <= n; i++){
 84         addedge(S, i << 1, 1);
 85         addedge(i << 1 | 1, T, 1);
 86     }
 87     for(int i = 1, x, y; i <= m; i++){
 88         addedge(x << 1, y << 1 | 1, 1);
 89     }
 90     int cnt = n - dinic();
 91     for(int i = 1; i <= n; i++) fa[i] = i;
 92     for(int i = 0; i <= esize; i += 2) {
 93         if(!edge[i].w && edge[i].v < S && edge[i].u < S){
 94             fa[find(edge[i].v >> 1)] = find(edge[i].u >> 1);
 95         }
 96     }
 97     for(int i = 1; i <= n; i++){
 98         if(find(i) == i){
 99             output(i << 1);
100             printf("\n");
101         }
102     }
103     printf("%d", cnt);
104     return 0;
105 }

Whole

原文地址:https://www.cnblogs.com/hjmmm/p/9278383.html

时间: 2024-10-07 12:55:13

【网络流24题 #03】最小路径覆盖问题的相关文章

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 的任何一个顶点开始,

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

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

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

传送门:>Here< 题意:求DAG的最小路径覆盖并输出方案.所谓最小路径覆盖是指,将原图分为若干条路径,任意两条路径不能有公共点,要使路径数量尽可能少 思路分析 依然能够联系到二分图.事实上这个问题在学二分图的时候提到过,然而当时并没有弄明白…… 公式:DAG的最小路径覆盖 = 顶点数 - 最大匹配 千万不要弄混淆的是这里的最大匹配并不是指直接在DAG上做最大匹配,而是需要拆点然后搞. 具体过程如下: 原图共有N个点.将每个点$i$拆成两个点,记为$X_i$与$Y_i$,对于任意一条原图中的

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<

[网络流专练3][最小路径覆盖问题]

题目描述 «问题描述: 给定有向图G=(V,E).设P 是G 的一个简单路(顶点不相交)的集合.如果V 中每个顶点恰好在P 的一条路上,则称P是G 的一个路径覆盖.P 中路径可以从V 的任何一个顶点开始,长度也是任意的,特别地,可以为0.G 的最小路径覆盖是G 的所含路径条数最少的路径覆盖.设计一个有效算法求一个有向无环图G 的最小路径覆盖.提示:设V={1,2,.... ,n},构造网络G1=(V1,E1)如下: 每条边的容量均为1.求网络G1的( 0 x , 0 y )最大流. «编程任务:

【COGS 461】[网络流24题] 餐巾 最小费用最大流

既然是最小费用最大流我们就用最大流来限制其一定能把每天跑满,那么把每个表示天的点向T连流量为其所需餐巾,费用为0的边,然后又与每天的餐巾对于买是无限制的因此从S向每个表示天的点连流量为INF,费用为一个餐巾的费用的边,然后我们考虑怎么用旧餐巾,我们用旧餐巾,要既不影响本点流量,也不影响本点费用,因此我们在开一坨点表示其对应得那天的旧餐巾,并通过他向离他快洗和离他慢洗天数的天的点连边,流量为Inf,费用为快洗.慢洗的费用,然后对于多余的旧餐巾,我们在一排天点中间从第一天连续地连到最后一天,流量为I

【网络流24题】

网络流 网络流24题 [最小路径覆盖问题] 关于输出路径,因为即使有反向弧经过左侧点也一定会改变左侧点的去向,若没连向右侧就会被更新到0,所以不用在意. mark记录有入度的右侧点,然后从没入度的右侧点开始把整条路径输出来即可. #include<cstdio> #include<algorithm> #include<cstring> using namespace std; const int maxn=100000,inf=0x3f3f3f3f; int n,m,

COGS728. [网络流24题] 最小路径覆盖问题

算法实现题8-3 最小路径覆盖问题(习题8-13) ´问题描述: 给定有向图G=(V,E).设P是G的一个简单路(顶点不相交)的集合.如果V中每个顶点恰好在P的一条路上,则称P是G的一个路径覆盖.P中路径可以从V的任何一个顶点开始,长度也是任意的,特别地,可以为0.G的最小路径覆盖是G的所含路径条数最少的路径覆盖.设计一个有效算法求一个有向无环图G的最小路径覆盖. 提示: 设V={1,2,...  ,n},构造网络G1=(V1,E1)如下: 每条边的容量均为1.求网络G1的(x0,y0)最大流.

网络流24题刷题记录

题目一:飞行员配对方案问题 一群飞行员和另一群飞行员之间有的可以配对,有的不能配对,求最多可以配多少对? 典型二分图最大匹配问题.可以用匈牙利算法 或者 加上源点汇点之后跑最大流.[感觉第二个打错的概率还低一些]. [还是介绍一下匈牙利算法吧][看白书大法好!] 从左边(s集)一个未盖点出发(还有没有和任何人匹配的点)出发,顺次经过未选边->选边->未选边.....[这样的路叫做交替路] 如果路径当中经过一个未盖点[这样的交替路叫增广路]...那么将所有的选边变成不选,不选的边选上,就可以多一