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

输入输出样例

输入 #1复制

11 12
1 2
1 3
1 4
2 5
3 6
4 7
5 8
6 9
7 10
8 11
9 11
10 11

输出 #1复制

1 4 7 10 11
2 5 8
3 6 9
3

说明/提示

1\leq n\leq 150,1\leq m\leq 60001≤n≤150,1≤m≤6000

由@FlierKing提供SPJ

思路

  既然是网络流24中的题目,就从网络流的方法下手吧。

  对于样例来说

  其实不难看出这题是和流的路径有关的。

  为了保证每个点只能用一次,

  可以考虑把每个点拆成出入两个点,

  它们之间的通道容量为1.

  由于起点终点的不确定,

  对整张图建立源点和汇点即可。

CODE

  1 #include <bits/stdc++.h>
  2 #define dbg(x) cout << #x << "=" << x << endl
  3 #define eps 1e-8
  4 #define pi acos(-1.0)
  5
  6 using namespace std;
  7 typedef long long LL;
  8
  9 const int inf = 0x3f3f3f3f;
 10
 11 template<class T>inline void read(T &res)
 12 {
 13     char c;T flag=1;
 14     while((c=getchar())<‘0‘||c>‘9‘)if(c==‘-‘)flag=-1;res=c-‘0‘;
 15     while((c=getchar())>=‘0‘&&c<=‘9‘)res=res*10+c-‘0‘;res*=flag;
 16 }
 17
 18 namespace _buff {
 19     const size_t BUFF = 1 << 19;
 20     char ibuf[BUFF], *ib = ibuf, *ie = ibuf;
 21     char getc() {
 22         if (ib == ie) {
 23             ib = ibuf;
 24             ie = ibuf + fread(ibuf, 1, BUFF, stdin);
 25         }
 26         return ib == ie ? -1 : *ib++;
 27     }
 28 }
 29
 30 int qread() {
 31     using namespace _buff;
 32     int ret = 0;
 33     bool pos = true;
 34     char c = getc();
 35     for (; (c < ‘0‘ || c > ‘9‘) && c != ‘-‘; c = getc()) {
 36         assert(~c);
 37     }
 38     if (c == ‘-‘) {
 39         pos = false;
 40         c = getc();
 41     }
 42     for (; c >= ‘0‘ && c <= ‘9‘; c = getc()) {
 43         ret = (ret << 3) + (ret << 1) + (c ^ 48);
 44     }
 45     return pos ? ret : -ret;
 46 }
 47
 48 const int maxn = 2e4 + 7;
 49
 50 int s, t, cnt;
 51 int head[maxn << 1], edge[maxn << 1], nxt[maxn << 1], vis[maxn << 1];
 52 int w[maxn << 1];//残量网络
 53 int rev[maxn << 1];
 54 int depth[maxn << 1];//图层
 55 int n, m;
 56
 57 void BuildGraph(int u, int v, int cap) {
 58     ++cnt;
 59     edge[cnt] = v;
 60     nxt[cnt] = head[u];
 61     rev[cnt] = cnt + 1;
 62     w[cnt] = cap;
 63     head[u] = cnt;
 64
 65     ++cnt;
 66     edge[cnt] = u;
 67     nxt[cnt] = head[v];
 68     w[cnt] = 0;
 69     rev[cnt] = cnt - 1;
 70     head[v] = cnt;
 71 }
 72
 73 bool bfs(int x) {
 74     queue<int> q;
 75     while(!q.empty()) {
 76         q.pop();
 77     }
 78     memset(depth, 63, sizeof(depth));
 79     depth[s] = 0;
 80     q.push(s);
 81     do {
 82         int u = q.front();
 83         q.pop();
 84         for ( int i = head[u]; i; i = nxt[i] ) {
 85             int v = edge[i];
 86             if(w[i] > 0 && depth[u] + 1 < depth[v]) {
 87                 depth[v] = depth[u] + 1;
 88                 q.push(v);
 89                 if(v == t) {
 90                     return true;
 91                 }
 92             }
 93         }
 94     } while (!q.empty());
 95     return false;
 96 }
 97
 98 int dfs(int u, int dist) {
 99     if(u == t) {
100         return dist;
101     }
102     for ( int i = head[u]; i; i = nxt[i] ) {
103         int v = edge[i];
104         if(depth[v] == depth[u] + 1 && w[i] > 0) {
105             int di = dfs(v, min(dist, w[i]));
106             if(di > 0) {
107                 w[i] -= di;
108                 w[rev[i]] += di;
109                 vis[u] = v;
110                 //printf("vis[%d]:%d\n",u, v);
111                 return di;
112             }
113         }
114     }
115     return 0;
116 }
117
118 int main()
119 {
120     //freopen("data.txt", "r", stdin);
121     memset(vis, 0, sizeof(vis));
122     read(n); read(m);
123     s = 0, t = 2 * n + 1;
124     for ( int i = 1; i <= m; ++i ) {
125         int u, v;
126         read(u); read(v);
127         BuildGraph(u, v + n, 1);
128     }
129     for ( int i = 1; i <= n; ++i ) {
130         BuildGraph(s, i, 1);
131         BuildGraph(n + i, t, 1);
132     }
133     int ans = 0;
134     while(bfs(s)) {
135         //cout << "!" << endl;
136         int res = dfs(0, 0x7f7f7f7f);
137         ans += res;
138     }
139     for ( int i = 1; i <= n; ++i ) {
140         if(vis[i]) {
141             int temp = i;
142             do {
143                 if(temp > n) {
144                     temp -= n;
145                 }
146                 printf("%d ",temp);
147                 int x = vis[temp];
148                 vis[temp] = 0;
149                 temp = x;
150             } while (temp != 0);
151             puts("");
152         }
153     }
154     printf("%d\n",n - ans);
155     return 0;
156 }

#include <bitsst#define dbg(x) cout << #x << "=" << x << endl#define eps 1e-8#define pi acos(-1.0)usingnamespacestd; typedeflonglong LL; constint inf = 0x3f3f3f3f; template<class T>inline void read(T &res) {char c;T flag=1; while((c=getchar())<‘0‘||c>‘9‘)if(c==‘-‘)flag=-1;res=c-‘0‘; while((c=getchar())>=‘0‘&&c<=‘9‘)res=res*10+c-‘0‘;res*=flag; } namespace _buff { constsize_t BUFF = 1 << 19; char ibuf[BUFF], *ib = ibuf, *ie = ibuf; char getc() { if (ib == ie) { ib = ibuf; ie = ibuf + fread(ibuf, 1, BUFF, stdin); } return ib == ie ? -1 : *ib++; } } int qread() { usingnamespace _buff; int ret = 0; bool pos = true; char c = getc(); for (; (c < ‘0‘ || c > ‘9‘) && c != ‘-‘; c = getc()) { assert(~c); } if (c == ‘-‘) { pos = false; c = getc(); } for (; c >= ‘0‘ && c <= ‘9‘; c = getc()) { ret = (ret << 3) + (ret << 1) + (c ^ 48); } return pos ? ret : -ret; } constint maxn = 2e4 + 7; int s, t, cnt; int head[maxn << 1], edge[maxn << 1], nxt[maxn << 1], vis[maxn << 1]; int w[maxn << 1];//残量网络int rev[maxn << 1]; int depth[maxn << 1];//图层int n, m; void BuildGraph(int u, int v, int cap) { ++cnt; edge[cnt] = v; nxt[cnt] = head[u]; rev[cnt] = cnt + 1; w[cnt] = cap; head[u] = cnt; ++cnt; edge[cnt] = u; nxt[cnt] = head[v]; w[cnt] = 0; rev[cnt] = cnt - 1; head[v] = cnt; } bool bfs(int x) { queue<int> q; while(!q.empty()) { q.pop(); } memset(depth, 63, sizeof(depth)); depth[s] = 0; q.push(s); do { int u = q.front(); q.pop(); for ( int i = head[u]; i; i = nxt[i] ) { int v = edge[i]; if(w[i] > 0 && depth[u] + 1 < depth[v]) { depth[v] = depth[u] + 1; q.push(v); if(v == t) { returntrue; } } } } while (!q.empty()); returnfalse; } int dfs(int u, int dist) { if(u == t) { return dist; } for ( int i = head[u]; i; i = nxt[i] ) { int v = edge[i]; if(depth[v] == depth[u] + 1 && w[i] > 0) { int di = dfs(v, min(dist, w[i])); if(di > 0) { w[i] -= di; w[rev[i]] += di; vis[u] = v; //printf("vis[%d]:%d\n",u, v);return di; } } } return0; } int main() { //freopen("data.txt", "r", stdin);memset(vis, 0, sizeof(vis)); read(n); read(m); s = 0, t = 2 * n + 1; for ( int i = 1; i <= m; ++i ) { int u, v; read(u); read(v); BuildGraph(u, v + n, 1); } for ( int i = 1; i <= n; ++i ) { BuildGraph(s, i, 1); BuildGraph(n + i, t, 1); } int ans = 0; while(bfs(s)) { //cout << "!" << endl;int res = dfs(0, 0x7f7f7f7f); ans += res; } for ( int i = 1; i <= n; ++i ) { if(vis[i]) { int temp = i; do { if(temp > n) { temp -= n; } printf("%d ",temp); int x = vis[temp]; vis[temp] = 0; temp = x; } while (temp != 0); puts(""); } } printf("%d\n",n - ans); return0; }

原文地址:https://www.cnblogs.com/orangeko/p/12639171.html

时间: 2024-08-01 18:54:56

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

P2764 最小路径覆盖问题(网络流24题之一)

题目描述 «问题描述: 给定有向图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 )最大流. «编程任务:

[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 个相邻球的编号之和为完全平方数. 试设计一个算法,计算出在

P2764 最小路径覆盖问题

题目描述 ?问题描述: 给定有向图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 )最大流. ?编程任务:

网络流24题!!!!

网1:飞行员匹配 题目链接:https://www.oj.swust.edu.cn/problem/show/1736 俩种做法: /**********二分图匹配做法***********/ #include<bits/stdc++.h> using namespace std; const int M=102; int n,m; int e[M][M],match[M],used[M]; bool find(int u){ for(int i=1;i<=m;i++){ if(e[u]

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

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 个相邻球的编号之和为完全平方数. 试设计一个算法,计算出在 

【网络流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]

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

网络流24题之 1738: 最小路径覆盖问题 最小路径覆盖问题 模板题,求一个图的最小路径覆盖,输出边数和,路径.不会输出路径的跑dinic然后把图输出来就懂了. #include <bits/stdc++.h> using namespace std; int k; struct Dinic { static const int MAXN = 30005 + 7; static const int MAXM = 1e7 + 7; static const int INF = 0x3f3f3f

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)最大流.

cogs_396_魔术球问题_(最小路径覆盖+二分图匹配,网络流24题#4)

描述 http://cojs.tk/cogs/problem/problem.php?pid=396 连续从1开始编号的球,按照顺寻一个个放在n个柱子上,\(i\)放在\(j\)上面的必要条件是\(i+j\)是一个完全平方数.问做多能放到几号球. 分析 cogs是简化版,我在网上找了个完整版的测试数据,要求输出方案... 求最大放几号球不方便,我们考虑枚举最大的球号,计算最少需要多少柱子. 我们对于满足\(j<i\)且\(i+j\)是一个完全平方数的\(i,j\),从\(j\)向\(i\)连一条