【网络流24题】最小路径覆盖问题

【网络流24题】最小路径覆盖问题

Description

给定有向图G=(V,E)。设P是G的一个简单路(顶点不相交)的集合。如果V中每个顶点恰好在P的一条路上,则称P是G的一个路径覆盖。P中路径可以从V的任何一个顶点开始,长度也是任意的,特别地,可以为0。G的最小路径覆盖是G的所含路径条数最少的路径覆盖。 
设计一个有效算法求一个有向无环图G的最小路径覆盖。

Input

第1行有2个正整数n和m。n是给定有向无环图G的顶点数,m是G的边数。 
接下来的m行,每行有2个正整数i 和j,表示一条有向边(i,j)。

Output

第1行开始,每行输出一条(字典序)路径。最后一行是最少路径数。

Sample Input

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

Sample Output

1 4 7 10 11 
2 5 8 
3 6 9 
3

Hint

数据范围: 
1<=n<=150,1<=m<=6000 
提示: 
设V={1,2,... ,n},构造网络G1=(V1,E1)如下: 
P 
每条边的容量均为1。求网络G1的(x0,y0)最大流。

一道巨坑题。。。这是链接【只有COGS支持SPJ,我也是呵呵了】

思路:既然每个点只能经过一次,不妨把一个点拆成A、B两点,对原图中a->b的边,连接a.A->b.B,跑一遍匈♂牙利,酱紫之后就可以发现点数-匹配数==剩下点数(废话),一条路径可以解决一堆剩下的点,于是ans=n-匹配数

 

 1 // It is made by XZZ
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<cstring>
 5 #define File
 6 #define Fname "path3"
 7 using namespace std;
 8 #define rep(a,b,c) for(rg int a=b;a<=c;a++)
 9 #define drep(a,b,c) for(rg int a=b;a>=c;a--)
10 #define erep(a,b) for(rg int a=fir[b];a;a=nxt[a])
11 #define il inline
12 #define rg register
13 #define vd void
14 #define t (dis[i])
15 typedef long long ll;
16 il int gi(){
17     rg int x=0;rg char ch=getchar();
18     while(ch<'0'||ch>'9')ch=getchar();
19     while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
20     return x;
21 }
22 const int maxn=151<<1,maxm=6002;
23 int id=0,fir[maxn],dis[maxm],nxt[maxm];
24 il vd add(int a,int b){
25     nxt[++id]=fir[a],fir[a]=id,dis[id]=b;
26 }
27 inline bool BFS() {
28     int bfs[maxn];
29     memset(dep,0,sizeof dep);
30     bfs.push(S);
31     bool yes[600]= {0};
32     yes[S]=1,dep[S]=0;
33     while(!bfs.empty()) {
34     int now=bfs.front();
35     for(int i=fir[now]; i; i=nxt[i])
36         if(w[i]>0&&!yes[t])
37         yes[t]=1,bfs.push(t),dep[t]=dep[now]+1;
38     bfs.pop();
39     }
40     return yes[T];
41 }
42 int dep[maxn];
43 inline int Dinic(int now,int h) {
44     if(now==T)return h;
45     int ans=0;
46     for(int i=fir[now]; i; i=nxt[i])
47     if(w[i]>0&&dep[t]==dep[now]+1) {
48         int D=Dinic(t,min(h,w[i]));
49         w[i]-=D,w[i^1]+=D,ans+=D,h-=D;
50         if(h==0)return ans;
51     }
52     return ans;
53 }
54 int main(){
55     freopen(Fname".in","r",stdin);
56     freopen(Fname".out","w",stdout);
57     rg int n=gi(),m=gi();
58     while(m--){rg int i=gi(),j=gi();add(i,j+n);}
59     memset(match,-1,sizeof match);
60     int ans=0;
61     drep(i,n,1){
62     memset(vis,0,sizeof vis);
63     vis[i]=1;if(dfs(i))++ans;
64     }
65     drep(i,n+n,n+1)if(match[i]+1)to[match[i]]=i-n,in[i-n]=1;
66     rep(i,1,n)if(!in[i]){
67     int now=i;printf("%d ",now);
68     while(to[now])now=to[now],printf("%d ",now);
69     puts("");
70     }
71     printf("%d\n",n-ans);
72     return 0;
73 }
View Code

 

posted @ 2017-07-20 13:11  菜狗xzz  阅读(205)  评论(0编辑  收藏  举报