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 }
  • 相关阅读:
    Checking Types Against the Real World in TypeScript
    nexus pip proxy config
    go.rice 强大灵活的golang 静态资源嵌入包
    几个golang 静态资源嵌入包
    rpm 子包创建学习
    Rpm Creating Subpackages
    ava 类似jest snapshot 功能试用
    ava js 测试框架基本试用
    The Architectural Principles Behind Vrbo’s GraphQL Implementation
    graphql-compose graphql schema 生成工具集
  • 原文地址:https://www.cnblogs.com/myx12345/p/11743831.html
Copyright © 2011-2022 走看看