zoukankan      html  css  js  c++  java
  • 【PowerOJ1738&网络流24题】最小路径覆盖问题 (最大流)

    题意:

     思路:

    【问题分析】

    有向无环图最小路径覆盖,可以转化成二分图最大匹配问题,从而用最大流解决。

    【建模方法】

    构造二分图,把原图每个顶点i拆分成二分图X,Y集合中的两个顶点Xi和Yi。对于原图中存在的每条边(i,j),在二分图中连接边(Xi,Yj)。然后把二分图最大匹配模型转化为网络流模型,求网络最大流。

    最小路径覆盖的条数,就是原图顶点数,减去二分图最大匹配数。沿着匹配边查找,就是一个路径上的点,输出所有路径即可。

    【建模分析】

    对于一个路径覆盖,有如下性质:

    1、每个顶点属于且只属于一个路径。

    2、路径上除终点外,从每个顶点出发只有一条边指向路径上的另一顶点。

    所以我们可以把每个顶点理解成两个顶点,一个是出发,一个是目标,建立二分图模型。该二分图的任何一个匹配方案,都对应了一个路径覆盖方案。如果匹配数为0,那么显然路径数=顶点数。每增加一

    条匹配边,那么路径覆盖数就减少一个,所以路径数=顶点数 - 匹配数。要想使路径数最少,则应最大化匹配数,所以要求二分图的最大匹配。

    注意,此建模方法求最小路径覆盖仅适用于有向无环图,如果有环或是无向图,那么有可能求出的一些环覆盖,而不是路径覆盖。

    DAG的最小路径覆盖=点数-二分图最大匹配

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 typedef long long ll;
      4 typedef unsigned int uint;
      5 typedef unsigned long long ull;
      6 typedef long double ld;
      7 typedef pair<int,int> PII;
      8 typedef pair<ll,ll> Pll;
      9 typedef vector<int> VI;
     10 typedef vector<PII> VII;
     11 //typedef pair<ll,ll>P;
     12 #define N  200010
     13 #define M  200010
     14 #define INF 1e9
     15 #define fi first
     16 #define se second
     17 #define MP make_pair
     18 #define pb push_back
     19 #define pi acos(-1)
     20 #define mem(a,b) memset(a,b,sizeof(a))
     21 #define rep(i,a,b) for(int i=(int)a;i<=(int)b;i++)
     22 #define per(i,a,b) for(int i=(int)a;i>=(int)b;i--)
     23 #define lowbit(x) x&(-x)
     24 #define Rand (rand()*(1<<16)+rand())
     25 #define id(x) ((x)<=B?(x):m-n/(x)+1)
     26 #define ls p<<1
     27 #define rs p<<1|1
     28 
     29 const ll MOD=1e9+7,inv2=(MOD+1)/2;
     30       double eps=1e-6;
     31       int dx[4]={-1,1,0,0};
     32       int dy[4]={0,0,-1,1};
     33 
     34 int head[N],vet[N],len[N],nxt[N],dis[N],num[N][2],vis[N],s,S,T,tot,n,m;
     35 
     36 int read()
     37 {
     38    int v=0,f=1;
     39    char c=getchar();
     40    while(c<48||57<c) {if(c=='-') f=-1; c=getchar();}
     41    while(48<=c&&c<=57) v=(v<<3)+v+v+c-48,c=getchar();
     42    return v*f;
     43 }
     44 
     45 void add(int a,int b,int c)
     46 {
     47     nxt[++tot]=head[a];
     48     vet[tot]=b;
     49     len[tot]=c;
     50     head[a]=tot;
     51 
     52     nxt[++tot]=head[b];
     53     vet[tot]=a;
     54     len[tot]=0;
     55     head[b]=tot;
     56 }
     57 
     58 bool bfs()
     59 {
     60     queue<int>q;
     61     rep(i,1,s) dis[i]=-1;
     62     q.push(S),dis[S]=0;
     63     while(!q.empty())
     64     {
     65         int u=q.front();
     66         q.pop();
     67         int e=head[u];
     68         while(e)
     69         {
     70             int v=vet[e];
     71             if(len[e]>0&&dis[v]==-1)
     72             {
     73                 dis[v]=dis[u]+1;
     74                 q.push(v);
     75             }
     76             e=nxt[e];
     77         }
     78     }
     79     return dis[T]!=-1;
     80 }
     81 
     82 int dfs(int u,int aug)
     83 {
     84     if(u==T) return aug;
     85     int e=head[u],val=0,flow=0;
     86     while(e)
     87     {
     88         int v=vet[e];
     89         if(len[e]>0&&dis[v]==dis[u]+1)
     90         {
     91             int t=dfs(v,min(len[e],aug));
     92             if(!t)
     93             {
     94                 e=nxt[e];
     95                 continue;
     96             }
     97             flow+=t;
     98             aug-=t;
     99             len[e]-=t;
    100             len[e^1]+=t;
    101             if(!aug) break;
    102         }
    103         e=nxt[e];
    104     }
    105     if(!flow) dis[u]=-1;
    106     return flow;
    107 }
    108 
    109 void print(int u)
    110 {
    111     //printf("u=%d
    ",u);
    112     if(u<=0||u==S) return;
    113     printf("%d ",u);
    114     int e=head[u];
    115     while(e)
    116     {
    117         int v=vet[e];
    118         if(!len[e]&&v<S) print(v-n);
    119         e=nxt[e];
    120     }
    121 }
    122 
    123 int main()
    124 {
    125     n=read(),m=read();
    126     s=0;
    127     rep(i,1,n) num[i][0]=++s;
    128     rep(i,1,n) num[i][1]=++s;
    129     S=++s; T=++s;
    130     rep(i,1,s) head[i]=0;
    131     tot=1;
    132     while(m--)
    133     {
    134         int x=read(),y=read();
    135         add(num[x][0],num[y][1],1);
    136     }
    137     rep(i,1,n) add(S,num[i][0],1);
    138     rep(i,1,n) add(num[i][1],T,1);
    139     int ans=n;
    140     while(bfs()) ans-=dfs(S,INF);
    141     int e=head[T];
    142     while(e)
    143     {
    144         int v=vet[e];
    145         if(len[e])
    146         {
    147             e=nxt[e];
    148             continue;
    149         }
    150         print(v-n);
    151         printf("
    ");
    152         e=nxt[e];
    153     }
    154 
    155     printf("%d
    ",ans);
    156     return 0;
    157 }
  • 相关阅读:
    【转】UTF8文件的Unicode签名BOM(Byte Order Mark)问题
    【转】java使用正则表达式去除字符串的html标签
    用UltraEdit转换大小写
    【转】浅谈字节序(Endianness)
    【转】用UltraEdit的正则表达式替换功能来格式化网页源代码
    【转】关于正则表达式匹配任意字符(包括换行符)的写法
    【转】C# 中的 #region 和 #endregion
    网易游戏开发工程师笔试题
    c++笔试题汇总
    恒生电子面试过程纪录
  • 原文地址:https://www.cnblogs.com/myx12345/p/11743831.html
Copyright © 2011-2022 走看看