算法实现题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)最大流。
´编程任务:
对于给定的给定有向无环图G,编程找出G的一个最小路径覆盖。
´数据输入:
由文件input.txt提供输入数据。文件第1行有2个正整数n和m。n是给定有向无环图
G的顶点数,m是G的边数。接下来的m行,每行有2个正整数i 和j,表示一条有向边(i,j)。
´结果输出:
程序运行结束时,将最小路径覆盖输出到文件output.txt中。从第1行开始,每行输出
一条路径。文件的最后一行是最少路径数。
输入文件示例
input.txt
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
输出文件示例
output.txt
1 4 7 10 11 2 5 8 3 6 9 3
数据范围:
1<=n<=150,1<=m<=6000
二分图匹配裸题,题面里都写了做法了
记录方案的话,多加个DFS看哪条弧被流过了就行
1 /*by SilverN*/ 2 #include<iostream> 3 #include<algorithm> 4 #include<cstring> 5 #include<cstdio> 6 #include<cmath> 7 #include<queue> 8 using namespace std; 9 const int INF=1e9; 10 const int mxn=20020; 11 int read(){ 12 int x=0,f=1;char ch=getchar(); 13 while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();} 14 while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();} 15 return x*f; 16 } 17 struct edge{ 18 int v,nxt,f; 19 }e[mxn*50]; 20 int hd[mxn],mct=1; 21 void add_edge(int u,int v,int w){ 22 e[++mct].v=v;e[mct].nxt=hd[u];e[mct].f=w;hd[u]=mct;return; 23 } 24 void insert(int u,int v,int c){ 25 add_edge(u,v,c);add_edge(v,u,0);return; 26 } 27 int n,m,S,T; 28 int d[mxn]; 29 bool BFS(){ 30 queue<int>q; 31 memset(d,0,sizeof d); 32 q.push(S); 33 d[S]=1; 34 while(!q.empty()){ 35 int u=q.front();q.pop(); 36 for(int i=hd[u];i;i=e[i].nxt){ 37 int v=e[i].v; 38 if(!d[v] && e[i].f){ 39 d[v]=d[u]+1; 40 q.push(v); 41 } 42 } 43 } 44 return d[T]; 45 } 46 int DFS(int u,int lim){ 47 if(u==T)return lim; 48 int f=0,tmp; 49 for(int i=hd[u];i;i=e[i].nxt){ 50 int v=e[i].v; 51 if(d[v]==d[u]+1 && e[i].f && (tmp=DFS(v,min(lim,e[i].f)))){ 52 f+=tmp;lim-=tmp; 53 e[i].f-=tmp; 54 e[i^1].f+=tmp; 55 if(!lim)return f; 56 } 57 } 58 d[u]=0; 59 return f; 60 } 61 int Dinic(){ 62 int res=0; 63 while(BFS())res+=DFS(S,INF); 64 return res; 65 } 66 int a[mxn],cnt=0; 67 bool vis[mxn]; 68 void Search(int u){ 69 vis[u]=1; 70 a[++cnt]=u; 71 for(int i=hd[u];i;i=e[i].nxt){ 72 int v=e[i].v; 73 if(v==S || v==T)continue; 74 if(!e[i].f && !vis[v]) 75 Search(v-n); 76 } 77 } 78 int main(){ 79 freopen("path3.in","r",stdin); 80 freopen("path3.out","w",stdout); 81 int i,j; 82 n=read();m=read(); 83 S=0;T=n+n+1; 84 for(i=1;i<=n;i++){ 85 insert(S,i,1); 86 insert(i+n,T,1); 87 } 88 int u,v; 89 for(i=1;i<=m;i++){ 90 u=read();v=read(); 91 insert(u,v+n,1); 92 } 93 int ans=n-Dinic(); 94 for(i=1;i<=n;i++){ 95 if(vis[i])continue; 96 cnt=0; 97 Search(i); 98 for(j=1;j<=cnt;j++) 99 printf("%d ",a[j]); 100 printf("\n"); 101 } 102 printf("%d\n",ans); 103 return 0; 104 }