算法实现题8-3 最小路径覆盖问题(习题8-13)
顶点恰好在P的一条路上,则称P是G的一个路径覆盖。P中路径可以从V的任何一个顶
点开始,长度也是任意的,特别地,可以为0。G的最小路径覆盖是G的所含路径条数最少
的路径覆盖。
设计一个有效算法求一个有向无环图G的最小路径覆盖。
每条边的容量均为1。求网络G1的(x0,y0)最大流。
G的顶点数,m是G的边数。接下来的m行,每行有2个正整数i 和j,表示一条有向边(i,j)。
输出文件示例
´问题描述:
给定有向图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)最大流。
´编程任务:
对于给定的给定有向无环图G,编程找出G的一个最小路径覆盖。´数据输入:
由文件input.txt提供输入数据。文件第1行有2个正整数n和m。n是给定有向无环图G的顶点数,m是G的边数。接下来的m行,每行有2个正整数i 和j,表示一条有向边(i,j)。
´结果输出:
程序运行结束时,将最小路径覆盖输出到文件output.txt中。从第1行开始,每行输出一条路径。文件的最后一行是最少路径数。
输入文件示例
input.txt11 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
输出文件示例
output.txt
1 4 7 10 11 2 5 8 3 6 9 3
数据范围:
1<=n<=150,1<=m<=6000
这题和网络流有什么关系,窝真是没想到。
似乎就是相当于把原图看成一张二分图,求最大匹配。
输出路径并没有怎么理解。。。
#include<iostream>
#include<cstring>
#include<cstdio>
#include<queue>
using namespace std;
const int N=155;
const int M=6005;
const int inf=1e9+7;
int n,m,s,t,ans,mct=1,hd[2*N],pre[2*N],nxt[2*N];
queue<int>q;
struct edge
{
int to,nxt,f;
}v[2*M+4*N];
void addedge(int x,int y,int z)
{
v[++mct].to=y;
v[mct].f=z;
v[mct].nxt=hd[x];
hd[x]=mct;
}
bool bfs()
{
memset(pre,0,sizeof(pre));
pre[s]=1;
q.push(s);
while(!q.empty())
{
int u=q.front();
q.pop();
for(int i=hd[u];i;i=v[i].nxt)
if(v[i].f&&!pre[v[i].to])
{
pre[v[i].to]=pre[u]+1;
q.push(v[i].to);
}
}
return pre[t];
}
int dfs(int u,int lft)
{
if(u==t||lft==0)
return lft;
int r=lft;
for(int i=hd[u];i;i=v[i].nxt)
if(r&&v[i].f&&pre[v[i].to]==pre[u]+1)
{
int w=dfs(v[i].to,min(r,v[i].f));
if(w>0)
{
v[i].f-=w,v[i^1].f+=w,r-=w;
nxt[u]=v[i].to;
if(!r)
return lft;
}
}
if(!r)
pre[u]=0;
return lft-r;
}
int main()
{
freopen("path3.in","r",stdin);
freopen("path3.out","w",stdout);
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);
addedge(x,y+n,1),addedge(y+n,x,0);
}
for(int i=1;i<=n;i++)
{
addedge(s,i,1),addedge(i,s,0);
addedge(i+n,t,1),addedge(t,i+n,0);
}
while(bfs())
ans+=dfs(s,inf);
for(int i=1;i<=n;i++)
if(nxt[i])
{
int c=i;
while(c)
{
if(c>=n)
c-=n;
printf("%d ",c);
int x=nxt[c];
nxt[c]=0;
c=x;
}
printf("\n");
}
printf("%d\n",n-ans);
return 0;
}