zoukankan      html  css  js  c++  java
  • 网络流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("
    ");
     99         }
    100     }
    101     printf("%d
    ",n-ans);
    102     return 0;
    103 }
  • 相关阅读:
    android 5.1 WIFI图标上的感叹号及其解决办法
    Recovery和Charger模式下屏幕旋转180度
    Android屏幕旋转总结
    Spring MVC 数据校验@Valid
    Spring注解装配
    Spring简单的REST例子
    Spring怎么引入多个xml配置文件
    spring使用c3p0报错
    Spring+JTA+Atomikos+MyBatis分布式事务管理
    (2-3)Eureka详解
  • 原文地址:https://www.cnblogs.com/nbwzyzngyl/p/8370753.html
Copyright © 2011-2022 走看看