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

Posted 大奕哥&VANE

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了网络流24题之最小路径覆盖问题相关的知识,希望对你有一定的参考价值。

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题之最小路径覆盖问题的主要内容,如果未能解决你的问题,请参考以下文章

网络流24题之魔术球问题

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

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

网络流24题 #03最小路径覆盖问题

「网络流24题」最小路径覆盖问题

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