码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2018-01-28 12:52:02      阅读:153      评论:0      收藏:0      [点我收藏+]

标签:xmlns   isp   print   row   overflow   idt   str   pre   oid   

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题之最小路径覆盖问题

标签:xmlns   isp   print   row   overflow   idt   str   pre   oid   

原文地址:https://www.cnblogs.com/nbwzyzngyl/p/8370753.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!