COGS728. [网络流24题] 最小路径覆盖问题

时间:2022-11-25 22:28:50

算法实现题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)如下:

COGS728. [网络流24题] 最小路径覆盖问题
每条边的容量均为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 }