• nyoj 谍战 (最小割最大流)


    做完图论学网络流。。  不会先转了。。

    转自http://blog.csdn.net/AQ14AQ1/article/details/38866407

    如果能想到是最小割问题,那么建图思路便是水到渠成的事了。

    添加一个源点S和汇点T;

    把S与每个间谍相连,容量为无穷大;

    把城市N(即飞机场的位置)与汇点T相连,容量为无穷大;

    之间有道路的城市相连,容量为1,注意这里是双向的边;

    建图完后,根据最大流最小割定理,那么直接求最大流即可。

      1 #include<iostream>
      2 using namespace std;
      3 #include<cstdio>
      4 #include<cstdlib>
      5 #include<cstring>
      6 #include<cmath>
      7 #include<string>
      8 #include<queue>
      9 #include<stack>
     10 #include<map>
     11 #include<vector>
     12 #include<algorithm>
     13 
     14 #define INS 1<<30
     15 #define CLR(arr,v) memset(arr,v,sizeof(arr))
     16 
     17 #define MaxV 3000
     18 #define MaxE 100000
     19 
     20 class MaxFlow{
     21 public:
     22     void Clear(){
     23         CLR(h,-1); CLR(cnt,0); CLR(vis,0);
     24         flag = false;
     25         pos = top = head = total = maxflow = 0;
     26     }
     27     void add(int u,int v,int flow){
     28         num[pos] = v;
     29         sur[pos] = flow;
     30         next[pos] = h[u];
     31         h[u] = pos++;
     32 
     33         num[pos] = u;
     34         sur[pos] = 0;
     35         next[pos] = h[v];
     36         h[v] = pos++;
     37     }
     38     int GetMaxFlow(int s,int t){
     39         init(t);
     40         stk[top] = s;
     41         while(!flag){
     42             minres = INS;
     43             if(top < 0) top = 0;
     44             if(!dfs(stk[top],-1,t,minres)) continue;
     45             maxflow += minres;
     46             while(dis != -1){
     47                 sur[dis] -= minres;
     48                 sur[dis^1] += minres;
     49                 dis = pre_e[dis];
     50             }
     51             top = 0;
     52         }
     53         return maxflow;
     54     }
     55 private:
     56     int h[MaxV],num[MaxE],sur[MaxE],next[MaxE],gap[MaxV],cnt[MaxV],pre_e[MaxE],stk[MaxV],que[MaxV];
     57     int pos,top,head,total,maxflow,minres,dis;
     58     bool vis[MaxV],flag;
     59     void init(int n){
     60         que[total++] = n;
     61         vis[n] = true;
     62         while(head < total){
     63             int p = que[head++];
     64             if(head >= MaxV) head -= MaxV;
     65             for(int i = h[p]; i != -1 ;i = next[i]){
     66                 if(!vis[ num[i] ]){
     67                     vis[ num[i] ] = true;
     68                     gap[ num[i] ] = gap[p] + 1;
     69                     cnt[ gap[ num[i] ] ]++;
     70                     que[total++] = num[i];
     71                     if(total >= MaxV) total -= MaxV;
     72                 }
     73             }
     74         }
     75     }
     76     bool dfs(int p,int father,int n,int &minres){
     77         int m = minres;
     78         for(int i = h[p]; i != -1 ;i = next[i]){
     79             if(sur[i] > 0 && gap[p] - gap[ num[i] ] == 1){
     80                 minres = min(minres,sur[i]);
     81                 pre_e[i] = father;
     82                 if(num[i] != n) stk[++top] = num[i];
     83                 if(num[i] == n || dfs(num[i],i,n,minres)) {
     84                     if(num[i] == n) dis = i;
     85                     return true;
     86                 }
     87                 minres = m;
     88             }
     89         }
     90         cnt[ gap[p] ]--;
     91         cnt[ gap[p] + 1]++;
     92         top--;
     93         if(cnt[ gap[p] ] == 0) flag = true;
     94         gap[p] += 1;
     95         return false;
     96     }
     97 }T;
     98 
     99 
    100 int main()
    101 {   
    102     int t;
    103     scanf("%d",&t);
    104     int cnt = 0;
    105     while (t--)
    106           {
    107           int n,m,p;
    108           scanf("%d%d%d",&n,&m,&p);
    109           
    110           int N = n + 1;
    111           T.Clear();
    112           
    113           int x;
    114           for (int i = 1; i <= p; ++ i)
    115                scanf("%d",&x),T.add(0,x,INS);
    116           
    117           for (int i = 1; i <= m; ++ i)
    118               {
    119               int u,v;
    120               scanf("%d%d",&u,&v);     
    121               T.add(u,v,1);
    122               T.add(v,u,1);
    123               }
    124           
    125           T.add(n,N,INS);
    126     
    127           printf("Case #%d: %d
    ",++cnt,T.GetMaxFlow(0,N));
    128           }
    129     return 0;
    130 }
  • 相关阅读:
    洛谷 P6599 「EZEC-2」异或 题解
    线段树懒标记以及标记永久化的两种实现方法(模板)
    洛谷P3834 【模板】可持久化线段树 1 题解
    Codeforces 1012B Chemical table (思维+二分图)
    HDU 6386 Age of Moyu (最短路+set)
    CodeForces 739B Alyona and a tree (二分+树上差分)
    Codeforces 444C DZY Loves Colors (线段树)
    HDU 5441 Travel (离线dsu)
    Codeforces 1000E We Need More Bosses (边双连通+最长链)
    CodeForces 219D Choosing Capital for Treeland (树形DP)经典
  • 原文地址:https://www.cnblogs.com/usedrosee/p/4337696.html
Copyright © 2020-2023  润新知