C、最小路径覆盖问题(有向无环图最小路径覆盖)(最大流)【省选/NOI- 】


拆点最大流

【问题分析】

有向无环图最小路径覆盖,可以转化成二分图最大匹配问题,从而用最大流解决。

【建模方法】

构造二分图,把原图每个顶点i拆分成二分图X,Y集合中的两个顶点Xi和Yi。对于原图中存在的每条边(i,j),在二分图中连接边(Xi,Yj)。然后把二分图最大匹配模型转化为网络流模型,求网络最大流。

最小路径覆盖的条数,就是原图顶点数,减去二分图最大匹配数。沿着匹配边查找,就是一个路径上的点,输出所有路径即可。

【建模分析】

对于一个路径覆盖,有如下性质:

1、每个顶点属于且只属于一个路径。 2、路径上除终点外,从每个顶点出发只有一条边指向路径上的另一顶点。

所以我们可以把每个顶点理解成两个顶点,一个是出发,一个是目标,建立二分图模型。该二分图的任何一个匹配方案,都对应了一个路径覆盖方案。如果匹配数为0,那么显然路径数=顶点数。每增加一条匹配边,那么路径覆盖数就减少一个,所以路径数=顶点数 - 匹配数。要想使路径数最少,则应最大化匹配数,所以要求二分图的最大匹配。

  • 节点:
源点0, 汇点1
图中第i个点: 左部分i, 右部分i + n
  • 弧:
(源点,左部分点,1)
(右部分点,汇点,1)
(i的左部分,j的右部分,1),前提是原图中i到j有一条有向边
  • 最大流:
(点数-最大流)即为最小路径覆盖
  • 输出答案
输出答案时,可以依次遍历未被访问的所有点,首先沿着反向弧找到路径起点,再依次输出并标记访问过即可。

注意,此建模方法求最小路径覆盖仅适用于有向无环图,如果有环或是无向图,那么有可能求出的一些环覆盖,而不是路径覆盖。

最后的方案可以利用残量网络用并查集维护。
即从 111 到 nnn 枚举,从每个点向外扫一圈,如果有流从这条边经过,也就是流量为 z=0z=0z=0 ,并流向 y+ny+ny+n ,说明这条边是最大流里的匹配边,将他们(xxx 与 yyy)合并为同一条边。

根据网络流的残余流量构造每一条路径(利用并查集维护路径起点),然后从起点递归输出。

Code

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;typedef long long ll;
typedef pair<int,int> PII;const int N = 2000 ,M = 60000 ,INF = 0x3f3f3f3f;int n,m,ans,S,T;
int ver[M],from[M],edge[M],nex[M],ln[M],head[N],tot = 1;
int maxflow;
int deep[N],now[M];
bool vis[N];
queue<int>q;
int fa[N];void add(int x,int y,int z){ver[++tot] = y;edge[tot] = z;from[tot] = x;nex[tot] = head[x];head[x] = tot;ver[++tot] = x;edge[tot] = 0;from[tot] = y;nex[tot] = head[y];head[y] = tot;
}bool bfs(){memset(deep,0x3f,sizeof deep);while(q.size())q.pop();q.push(S);deep[S] = 0;now[S] = head[S];while(q.size()){int x = q.front();q.pop();for(int i = head[x];i;i = nex[i]){int y = ver[i],z = edge[i];if(z > 0 && deep[y] == INF){q.push(y);now[y] = head[y];deep[y] = deep[x] + 1;if(y == T)return true;}}}return false;
}int dfs(int x,int flow){if(x == T || !flow)return flow;int ans = 0,k,i;for(int i = now[x];i && flow;i = nex[i]){now[x] = i;//当前弧优化int y = ver[i],z = edge[i];if(z > 0 && (deep[y] == deep[x] + 1)){k = dfs(y,min(flow,z));if(!k)deep[y] = INF;edge[i] -=k;edge[i ^ 1] += k;ans += k;flow -= k;}}return ans;
}void Dinic(){while(bfs()){for(int i = 1;i <= n;++i)now[i] = head[i];while(int d = dfs(S,INF))maxflow += d;}
}int Find(int x){if(fa[x] == x)return x;return fa[x] = Find(fa[x]);
}void unite(int x,int y){x = Find(x),y = Find(y);if(x != y)fa[x] = y;
}void output(int x){printf("%d ",x);for(int i = head[x];i;i = nex[i]){int y = ver[i],z = edge[i];if(!z && y > n)output(y - n);}
}void print(){for(int i = 1;i <= n;++i)fa[i] = i;for(int i = 1;i <= tot;++i){int u = from[i],v = ver[i],z = edge[i];if(u >= 1 && u <= n && v > n && v < T && !z)unite(v - n,u);}for(int i = 1;i <= n;++i)if(Find(i) == i)output(i),puts("");printf("%d\n",ans);
}int main(){scanf("%d%d",&n,&m);S = 0,T = 2 * n + 1;for(int i = 1;i <= m;++i){int x,y;scanf("%d%d",&x,&y);add(x,y + n,1);}for(int i = 1;i <= n;++i)add(S,i,1),add(i + n,T,1);Dinic();ans = n - maxflow;//cout<<maxflow<<"#"<<endl;print();return 0;
}

【网络流24题】解题报告:C、最小路径覆盖问题(有向无环图最小路径覆盖)(最大流)相关推荐

  1. 【网络流24题】D、魔术球问题(有向无环图的最小路径覆盖、思维)

    D.魔术球问题(有向无环图的最小路径覆盖.思维)[省选/NOI- ] P2765 魔术球问题 [问题分析] 枚举答案转化为判定性问题,然后最小路径覆盖,可以转化成二分图最大匹配,从而用最大流解决. [ ...

  2. 网络流24题——魔术球问题(有向无环图最小路径覆盖)

    链接:https://www.oj.swust.edu.cn/oj/problem/show/1739 分析: 有向无环图最小路径覆盖:给定有向无环图,求一个路径划分,使得每个点在且只在一条路径上,路 ...

  3. 【网络流24题】B、太空飞行计划问题(最大权闭合图转最小割、最小割方案输出)

    整理的算法模板合集: ACM模板 B.太空飞行计划问题(最大权闭合图转最小割.最小割方案输出)[省选/NOI- ] P2762 太空飞行计划问题 [问题分析] 最大权闭合图问题,可以转化成最小割问题, ...

  4. 解题报告:线性规划与网络流24题

    目录 A.飞行员配对方案问题 (二分图最大匹配)(最大流)[提高+/省选- ] B.太空飞行计划问题(最大权闭合图转最小割.最小割方案输出)[省选/NOI- ] C.最小路径覆盖问题(有向无环图最小路 ...

  5. [线性规划与网络流24题] 网络流常见模型

    最近两个月在做<线性规划与网络流24题>这套题,加深了对网络流的理解. 涵盖到的模型有:二分图匹配.二分图的最大独立集.最大权闭合图.有向无环图的最小路径覆盖.最多不相交路径.最大权不相交 ...

  6. 【线性规划和网络流24题】

    (1)飞行员配对方案问题:二分图最大匹配. 思路:略. View Code 1 #include<cstdio> 2 #include<cstring> 3 #define M ...

  7. 【网络流24题】 No.3 最小路径覆盖问题 (网络流|匈牙利算法 -最大二分匹配)...

    [题意] 给定有向图 G=(V,E).设 P 是 G 的一个简单路(顶点不相交) 的集合.如果 V 中每个 顶点恰好在 P 的一条路上,则称 P 是 G 的一个路径覆盖. P 中路径可以从 V 的任何 ...

  8. 流网络的最小割问题c语言,「网络流24题」最小路径覆盖问题

    Description 问题描述: 给定有向图G=(V,E).设P 是G 的一个简单路(顶点不相交)的集合.如果V 中每个顶点恰好在P 的一条路上,则称P是G 的一个路径覆盖.P 中路径可以从V 的任 ...

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

    Description 问题描述: 给定有向图G=(V,E).设P 是G 的一个简单路(顶点不相交)的集合.如果V 中每个顶点恰好在P 的一条路上,则称P是G 的一个路径覆盖.P 中路径可以从V 的任 ...

最新文章

  1. poj3061(二分算法)
  2. idea教程--使用mave创建普通java项目
  3. 普通人也要学python吗-普通人学Python有意义吗?
  4. EntityFramework 7 OrderBy Skip Take-计算排序分页 SQL 翻译
  5. aix 的c库为什么都是静态库_关于AIX  libpthread.a 静态库
  6. ArcGIS js api 手动构建FeatureLayer
  7. SPSS22.0简体中文破解版(32位/64位)使用方法
  8. linux 终端命令字体大小,如何更改Ubuntu终端的字体和字体大小
  9. 工业级手持式扫描仪3d扫描首选迪万科技抄数服务
  10. TP6------图片上传/多图上传
  11. KubeSphere 部署
  12. 邢台一中2021年许计勇高考成绩查询,文理Top10!2020邢台高考成绩揭晓...
  13. 算法LeetCode解题(C++)-15. 四数之和(难度:中等)
  14. 如何使用Graylog来收集日志?
  15. Mac搜不到wifi
  16. Excel使用技巧总结二
  17. Swift如何兼顾协议中默认和自定义方法的调用?
  18. 【计算机网络】思科实验(4):综合实验作业之办公室的跨VLAN通信
  19. win10安装Andorid Studio常见问题
  20. 【JavaScript】用户代理检测的局限性

热门文章

  1. 北大博士整理B站实战项目!yyds!
  2. 8个计算机视觉深度学习中常见的Bug
  3. 【微信公众号开发】获取并保存access_token、jsapi_ticket票据(可用于微信分享、语音识别等等)...
  4. 常见apk安装失败的错误及原因
  5. 苹果向求职者抛出的8大难题
  6. C语言 fread()与fwrite()函数说明与示例
  7. 项目的技术路线怎么写_资讯丨空压机节能改造项目技术路线
  8. 入门月薪8k,3年经验年薪30w,大数据薪酬待遇竟这么高?
  9. Java开发四年的程序员想再学习一门语言,该选着C还是Python呢?
  10. 忘了python关键语句?这份备忘录拯救你的记忆