1. 程式人生 > >網絡流24題之最小路徑覆蓋問題

網絡流24題之最小路徑覆蓋問題

覆蓋問題 front ron != leg amp mes span n-1

DAG的最小不相交路徑覆蓋

算法:把原圖的每個點V拆成Vx

Vy兩個點,如果有一條有向邊A->B,那麽就加邊Ax>By

。這樣就得到了一個二分圖。那麽最小路徑覆蓋=原圖的結點數-新圖的最大匹配數。

證明:一開始每個點都是獨立的為一條路徑,總共有n條不相交路徑。我們每次在二分圖裏找一條匹配邊就相當於把兩條路徑合成了一條路徑,也就相當於路徑數減少了1。所以找到了幾條匹配邊,路徑數就減少了多少。所以有最小路徑覆蓋=原圖的結點數-新圖的最大匹配數。

因為路徑之間不能有公共點,所以加的邊之間也不能有公共點,這就是匹配的定義。

我這裏給出網絡流的寫法,建立源點匯點,連流量為1的邊,然後答案就是點數-最大流

By:大奕哥

  1 #include<iostream>
  2 #include<cstdlib>
  3 #include<cstdio>
  4 #include<algorithm>
  5 #include<cstring>
  6 #include<queue>
  7 #include<vector>
  8 #include<cmath>
  9 using namespace std;
 10 const int N=10005;
 11 int n,m,s=0
,t=10000,head[N],d[N],vis[N],cnt=-1; 12 inline int read(){ 13 int x=0,f=1;char ch=getchar(); 14 while(ch<0||ch>9){if(ch==-)f=-1;ch=getchar();} 15 while(ch>=0&&ch<=9)x=(x<<1)+(x<<3)+ch-0,ch=getchar(); 16 return x*f; 17 } 18 struct node{
19 int to,nex,w; 20 }e[N<<1]; 21 void add(int x,int y,int w) 22 { 23 e[++cnt].to=y;e[cnt].w=w;e[cnt].nex=head[x];head[x]=cnt; 24 e[++cnt].to=x;e[cnt].w=0;e[cnt].nex=head[y];head[y]=cnt; 25 } 26 queue<int>q; 27 bool bfs(int x,int y) 28 { 29 memset(d,-1,sizeof(d)); 30 d[x]=0;q.push(x); 31 while(!q.empty()) 32 { 33 int x=q.front();q.pop(); 34 for(int i=head[x];i!=-1;i=e[i].nex) 35 { 36 int y=e[i].to; 37 if(!e[i].w||d[y]!=-1)continue; 38 d[y]=d[x]+1; 39 q.push(y); 40 } 41 } 42 return d[y]!=-1; 43 } 44 int dfs(int x,int w,int yy) 45 { 46 if(!w||x==yy)return w; 47 int s=0; 48 for(int i=head[x];i!=-1;i=e[i].nex) 49 { 50 int y=e[i].to; 51 if(!e[i].w||d[y]!=d[x]+1)continue; 52 int flow=dfs(y,min(w-s,e[i].w),yy); 53 if(!flow){ 54 d[y]=-1;continue; 55 } 56 e[i].w-=flow;e[i^1].w+=flow; 57 vis[x]=y;s+=flow; 58 if(s==w)return s; 59 } 60 return s; 61 } 62 int dinic() 63 { 64 int ans=0; 65 while(bfs(s,t)){ 66 ans+=dfs(s,1e9,t); 67 } 68 return ans; 69 } 70 int main() 71 { 72 n=read();m=read();int x,y; 73 memset(head,-1,sizeof(head)); 74 for(int i=1;i<=m;++i) 75 { 76 x=read();y=read(); 77 add(x,y+n,1); 78 } 79 for(int i=1;i<=n;++i) 80 { 81 add(s,i,1); 82 add(i+n,t,1); 83 } 84 int ans=dinic(); 85 for(int i=1;i<=n;++i) 86 { 87 if(vis[i]) 88 { 89 int pos=i; 90 while(pos) 91 { 92 if(pos>n)pos-=n; 93 printf("%d ",pos); 94 int x=vis[pos]; 95 vis[pos]=0; 96 pos=x; 97 } 98 printf("\n"); 99 } 100 } 101 printf("%d\n",n-ans); 102 return 0; 103 }

網絡流24題之最小路徑覆蓋問題