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 }
  • 相关阅读:
    打造绿色JRE
    AOSP(Android Open Source Project) Android开源项目
    SyncML协议简述
    诺基亚 索爱 低端手机及智能手机 与 QQ邮箱或MyTT 通讯录同步 介绍
    Android 的源代码结构
    recovery v1跟recovery v2的区别
    Android系统架构
    haoGOD6.6 修改自XDA的thedroidsector的kingkernel #8 04/22
    下一代Android或官方支持“App2sd”
    Android 中的微型云
  • 原文地址:https://www.cnblogs.com/nbwzyzngyl/p/8370753.html
Copyright © 2011-2022 走看看