洛谷 P2764(最小路径覆盖=节点数-最大匹配)
2018-08-23 21:40
423 查看
给定有向图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 )最大流。
«编程任务:
对于给定的给定有向无环图G,编程找出G的一个最小路径覆盖。
输入输出格式
输入格式:
件第1 行有2个正整数n和m。n是给定有向无环图G 的顶点数,m是G 的边数。接下来的m行,每行有2 个正整数i和j,表示一条有向边(i,j)。
输出格式:
从第1 行开始,每行输出一条路径。文件的最后一行是最少路径数。
输入输出样例
输入样例#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<=n<=150,1<=m<=6000
由@FlierKing提供SPJ
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<queue> #include<cmath> #include<vector> using namespace std; #define INF 0x3f3f3f3f const int maxn = 6e4+10; int n,m,s,t,u,v; struct Edge { int from, to, cap, flow; }; vector<Edge> edges; vector<int> G[maxn]; bool vis[maxn]; int d[maxn], cur[maxn],nxt[maxn]; void Init() { memset(d,0,sizeof d); for(int i=0;i<=2*n+1;i++) G[i].clear(); } void AddEdge(int from, int to, int cap) { edges.push_back((Edge){from, to, cap, 0}); edges.push_back((Edge){to, from, 0, 0}); int m = edges.size(); G[from].push_back(m-2); G[to].push_back(m-1); } bool bfs() { memset(vis,0,sizeof vis); queue<int> q; q.push(s); d[s] = 0; vis[s] = 1; while (!q.empty()) { int x = q.front(); q.pop(); for(int i = 0; i < G[x].size(); ++i) { Edge &e = edges[G[x][i]]; if (!vis[e.to] && e.cap > e.flow) { vis[e.to] = 1; d[e.to] = d[x] + 1; q.push(e.to); } } } return vis[t]; } int dfs(int x,int a) { if(x == t || a == 0) return a; int flow = 0, f; for(int &i = cur[x]; i < G[x].size(); ++i) { Edge &e = edges[G[x][i]]; if (d[e.to] == d[x] + 1 && (f=dfs(e.to, min(a, e.cap-e.flow))) > 0) { e.flow += f; edges[G[x][i]^1].flow -= f; flow += f; a -= f; if (a == 0) break; } } return flow; } int MaxFlow(int s, int t) { int flow = 0; while (bfs()) { memset(cur,0,sizeof cur); flow += dfs(s, INF); } return flow; } int main() { while(scanf("%d%d",&n,&m)!=EOF) { Init(); for(int i=1;i<=m;i++) { scanf("%d%d",&u,&v); AddEdge(u,v+n,1); } s=0,t=2*n+1; for(int i=1;i<=n;i++) { AddEdge(s,i,1); AddEdge(i+n,t,1); } int ans=MaxFlow(s,t); memset(nxt,0,sizeof nxt); memset(vis,0,sizeof vis); for(int i=1;i<=n;i++) { for(int j=0;j<G[i].size();j++) { Edge &e=edges[G[i][j]]; if(e.flow>0) nxt[e.from]=e.to-n; } } for(int i=1;i<=n;i++) { if(!vis[i]) { int a=i; vis[a]=1; printf("%d",a); while(nxt[a]) { a=nxt[a]; vis[a]=1; printf(" %d",a); } printf("\n"); } } printf("%d\n",n-ans); } return 0; }
相关文章推荐
- 洛谷P2764 最小路径覆盖问题(最大流)
- Air Raid(最小路径覆盖数=节点数-最大匹配数)
- POJ - 1422 Air Raid (最小路径覆盖 = 总点数 - 最大匹配)
- UVa live3126Taxi Cab Scheme(二分最大匹配之最小路径覆盖)
- poj1422 Air Raid 最小路径覆盖=顶点数-最大匹配数
- loj6002「网络流 24 题」最小路径覆盖(最小路径覆盖+二分图最大匹配)
- HDU 1151Air Raid 最小路径覆盖=n-最大匹配量 (第二道二分匹配)
- 浅显易懂二分图-最大匹配,最小路径覆盖,最小点覆盖
- 二分图大讲堂——彻底搞定最大匹配数(最小覆盖数)、最大独立数、最小路径覆盖、带权最优匹配
- 二分图最大匹配,点的最小覆盖,最小路径覆盖
- 二分图大讲堂——彻底搞定最大匹配数(最小覆盖数)、最大独立数、最小路径覆盖、带权最优匹配
- Antenna Placement poj3020(二分图最大匹配/最小路径覆盖)
- 最大匹配、最小顶点覆盖、最大独立集、最小路径覆盖(转)
- HDU 1151Air Raid 最小路径覆盖=n-最大匹配量 (第二道二分匹配)
- poj3020_最小覆盖路径(顶点个数-二分图最大匹配数)
- Taxi Cab Scheme UVALive - 3126 最小路径覆盖解法(必须是DAG,有向无环图) = 结点数-最大匹配
- HDU1151_Air Raid(二分图/最小路径覆盖=n-最大匹配)
- 二分图大讲堂——彻底搞定最大匹配数(最小覆盖数)、最大独立数、最小路径覆盖、带权最优匹配
- 二分图——最大匹配数(最小覆盖数)、最大独立数、最小路径覆盖、带权最优匹配
- 最大匹配、最小顶点覆盖、最大独立集、最小路径覆盖(转)