P2764 最小路径覆盖问题(网络流)
2018-03-27 07:55
381 查看
题目描述
给定有向图G=(V,E)G=(V,E)。设PP是GG的一个简单路(顶点不相交)的集合。如果VV中每个顶点恰好在PP的一条路上,则称PP是GG的一个路径覆盖。PP 中路径可以从VV 的任何一个顶点开始,长度也是任意的,特别地,可以为0。GG 的最小路径覆盖是GG 的所含路径条数最少的路径覆盖。设计一个有效算法求一个有向无环图GG 的最小路径覆盖。输入格式:
件第1 行有2个正整数nn和mm。nn是给定有向无环图GG 的顶点数,mm是GG 的边数。接下来的mm行,每行有2 个正整数ii和jj,表示一条有向边(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≤60001≤n≤150,1≤m≤6000传送门!!!
解:
这是一个网络流的套路,这玩意都能建网络流,orz,蒟蒻无话可说。对于每一个点,它最多有两条边在路径当中,所以我们建网络流,点一分为二,在图中相连的点进行连边,汇点连1,源点连1,中间连infinf跑最大流。最大流的意义就是最小路径覆盖中连边的条数。我们用n−flow(流量)n−flow(流量)就是答案。
画个图理解一下:
红色就代表了选择的连边,1−2−3−4,5,1−2−3−4,5,两条路。显然有多解,所以有spj。
#include<cstdio> #include<iostream> #include<cstring> #include<queue> using namespace std; struct lxy{ int to,next,flow; }b[50005]; int n,m,cnt=-1,head[505],s,t,num; int layer[505]; int const inf=0x7f7f7f7f; int to[155];bool vis[155]; int ans; void add(int op,int ed,int flow) { b[++cnt].next=head[op]; b[cnt].to=ed; b[cnt].flow=flow; head[op]=cnt; } bool bfs() { memset(layer,0,sizeof(layer)); queue <int> d; layer[s]=1;d.push(s); while(!d.empty()) { int now=d.front(); d.pop(); for(int i=head[now];i!=-1;i=b[i].next) if(b[i].flow!=0&&layer[b[i].to]==0) { layer[b[i].to]=layer[now]+1; d.push(b[i].to); } } return layer[t]; } int dfs(int u,int a) { if(a==0||u==t) return a; int f,flow=0; for(int i=head[u];i!=-1;i=b[i].next) if(b[i].flow!=0&&layer[u]+1==layer[b[i].to]) { f=dfs(b[i].to,min(a,b[i].flow)); b[i].flow-=f; b[i^1].flow+=f; flow+=f; a-=f; if(a==0) break; } return flow; } int dinic() { int ans=0; while(bfs()) ans+=dfs(s,inf); return ans; } int main() { scanf("%d%d",&n,&m);t=n*2+1;num=n; for(int i=0;i<=n*2+1;i++) head[i]=-1; for(int i=1;i<=m;i++) { int x,y;scanf("%d%d",&x,&y); add(x,y+n,1);add(y+n,x,0); } for(int i=1;i<=n;i++) add(s,i,1),add(i,s,0); for(int i=n+1;i<=n*2;i++) add(i,t,1),add(t,i,0); ans=num-dinic(); for(int i=1;i<=n;i++) { for(int j=head[i];j!=-1;j=b[j].next) if(b[j].flow==0) to[i]=b[j].to-n; } for(int i=1;i<=n;i++) if(vis[i]==0) { int p=i; while(p!=-n) { vis[p]=1; printf("%d ",p); p=to[p]; } printf("\n"); } printf("%d",ans); }
相关文章推荐
- 洛谷 P2764 最小路径覆盖问题【网络流||二分图匹配】
- P2764 最小路径覆盖问题(网络流24题之一)
- 网络流24题3最小路径覆盖问题(洛谷 P2764 最小路径覆盖问题)
- [网络流24题][CODEVS1904]最小路径覆盖问题(最大流||匈牙利算法)
- 洛谷 P2764 最小路径覆盖问题【匈牙利算法】
- 洛谷P2764 最小路径覆盖问题(最大流)
- 网络流24题 最小路径覆盖问题
- [网络流24题 #3]最小路径覆盖问题
- 线性规划与网络流24题 3最小路径覆盖问题 NEFU 481
- 最小路径覆盖问题 (网络流解法)
- COGS 728. [网络流24题] 最小路径覆盖问题
- 网络流二十四题之三 —— 最小路径覆盖问题(PATH)
- 「网络流24题」最小路径覆盖问题
- [网络流24题]最小路径覆盖问题
- 线性规划与网络流24题 3最小路径覆盖问题 NEFU 481
- 网络流之最小路径覆盖问题
- 线性规划与网络流24题 03最小路径覆盖问题
- 网络流24题之T3——最小路径覆盖问题
- ssl 2603 网络流24题3 最小路径覆盖问题
- 【网络流二十四题 魔术球问题】【DAG 最小路径覆盖->最大流】【灵感】