zoukankan      html  css  js  c++  java
  • 【网络流之最大权闭包专题】解题报告

     最大权闭包模型中源点与正收益的点连边,负收益的点与汇点连边,容量取绝对值,然后相关联的点之间之间连容量为无穷大的边。

     具体可参见胡伯涛:《最小割模型在信息学竞赛中的应用》

    HDU 3061 Battle

      应该是最裸的最大权闭包题了。

      1 #include <vector>
      2 #include <list>
      3 #include <map>
      4 #include <set>
      5 #include <queue>
      6 #include <deque>
      7 #include <stack>
      8 #include <algorithm>
      9 #include <sstream>
     10 #include <iostream>
     11 #include <iomanip>
     12 #include <cstdio>
     13 #include <cstdlib>
     14 #include <cstring>
     15 #include <cmath>
     16 #include <queue>
     17 using namespace std;
     18 #define pii         pair<LL,LL>
     19 #define    clr(a)      memset((a),0,sizeof (a))
     20 #define    rep(i,a,b)  for(LL i=(a);i<=(LL)(b);i++)
     21 #define    per(i,a,b)  for(LL i=(a);i>=(LL)(b);i--)
     22 #define oo          ((LL)2000000007)*((LL)2000000007)
     23 #define    eps         1e-6
     24 #define    MAXN        1005
     25 #define MAXM        200005
     26 #define MOD         1000000007
     27 #define debug       puts("reach here")
     28 #define MP          make_pair
     29 #define PB          push_back
     30 #define RI(x)       scanf("%I64d",&x)
     31 #define RII(x,y)    scanf("%I64d%I64d",&x,&y)
     32 #define RIII(x,y,z) scanf("%d%d%d",&x,&y,&z)
     33 typedef long long LL;
     34 
     35 struct Edge
     36 {
     37     int u, v, next;
     38     LL w;
     39 }E[MAXM];     
     40 
     41 int gap[MAXN], pre[MAXN], cur[MAXN], dis[MAXN];
     42 LL n, m;
     43 LL N;
     44 int head[MAXN], NE;
     45 bool vis[MAXN];
     46 
     47 void add_edge (int u, int v, LL w)
     48 {
     49     E[NE].u = u; E[NE].v = v; E[NE].w = w; E[NE].next = head[u]; head[u] = NE++;
     50     E[NE].u = v; E[NE].v = u; E[NE].w = 0; E[NE].next = head[v]; head[v] = NE++;
     51 }
     52 
     53 inline void checkmin(LL &a,LL b)  {if(a == -1 || a > b)a = b;}
     54 
     55 LL sap(int s, int t)
     56 {
     57     clr(dis); clr(gap);
     58     for(int i=0;i<N;++i) cur[i]=head[i];
     59     int u=pre[s]=s;
     60     LL maxflow=0;
     61     LL aug=-1;
     62     gap[0]=N;
     63     while(dis[s]<N)
     64     {
     65 loop:for(int &i=cur[u];i!=-1;i=E[i].next)
     66         {
     67             LL v=E[i].v;
     68             if(E[i].w && dis[u]==dis[v]+1)
     69             {
     70                 checkmin(aug,E[i].w);
     71                 pre[v]=u;
     72                 u=v;
     73                 if(v==t)
     74                 {
     75                     maxflow += aug;
     76                     for(u=pre[u];v!=s;v=u,u=pre[u])
     77                     {
     78                         E[cur[u]].w-=aug;
     79                         E[cur[u]^1].w+=aug;
     80                     }
     81                     aug=-1;
     82                 }
     83                 goto loop;
     84             }
     85         }
     86         int mindis=N;
     87         for(int i=head[u];i!=-1;i=E[i].next)
     88         {
     89             int v=E[i].v;
     90             if(E[i].w && mindis>dis[v])
     91             {
     92                 cur[u]=i;
     93                 mindis=dis[v];
     94             }
     95         }
     96         if((--gap[dis[u]])==0) break;
     97         gap[dis[u]=mindis+1]++;
     98         u=pre[u];
     99     }
    100     return maxflow;
    101 }
    102 
    103 void init()
    104 {
    105     NE = 0; 
    106     memset(head, -1, sizeof head);
    107 }
    108 
    109 int main()
    110 {
    111     int a, b;
    112     LL sum, v;
    113     while(RII(n, m) != EOF)
    114     {
    115         init();
    116         LL s = 0, t = n + 1;
    117         sum = 0;
    118         N = t + 1;
    119         rep(i,1,n)
    120         {
    121             RI(v);
    122             if(v > 0)
    123             {
    124                 add_edge(s, i, v);
    125                 sum += v;
    126             }
    127             else
    128                 add_edge(i, t, -v);
    129         }
    130         rep(i,1,m)
    131         {
    132             scanf("%d%d", &a, &b);
    133             add_edge(a, b, oo);
    134         }
    135        printf("%I64d
    ", sum - sap(s, t));
    136     }
    137     return 0;
    138 }
    View Code

    HDU 3879 Base Station

      所给的m条边是正收益,所给的n个点是负收益,此时,把正收益的m条边变为点

      那么,对于连接a b两点的边k,这样建图:

      1. 源点与k连边,权值为题目所给边权

      2. k分别于a和b连边,权值为无穷大

      3. 所有节点和汇点连边,权值为该点花费的绝对值

      1 #include <vector>
      2 #include <list>
      3 #include <map>
      4 #include <set>
      5 #include <queue>
      6 #include <deque>
      7 #include <stack>
      8 #include <algorithm>
      9 #include <sstream>
     10 #include <iostream>
     11 #include <iomanip>
     12 #include <cstdio>
     13 #include <cstdlib>
     14 #include <cstring>
     15 #include <cmath>
     16 #include <queue>
     17 using namespace std;
     18 #define pii         pair<LL,LL>
     19 #define clr(a)      memset((a),0,sizeof (a))
     20 #define rep(i,a,b)  for(LL i=(a);i<=(LL)(b);i++)
     21 #define per(i,a,b)  for(LL i=(a);i>=(LL)(b);i--)
     22 #define oo          1000000000
     23 #define eps         1e-6
     24 #define MAXN        85005
     25 #define MAXM        2000005
     26 #define MOD         1000000007
     27 #define debug       puts("reach here")
     28 #define MP          make_pair
     29 #define PB          push_back
     30 #define RI(x)       scanf("%d",&x)
     31 #define RII(x,y)    scanf("%d%d",&x,&y)
     32 #define RIII(x,y,z) scanf("%d%d%d",&x,&y,&z)
     33 typedef long long LL;
     34  
     35 struct Edge
     36 {
     37     int u, v, next;
     38     LL w;
     39 }E[MAXM];     
     40  
     41 int gap[MAXN], pre[MAXN], cur[MAXN], dis[MAXN];
     42 int n, m, N;
     43 int head[MAXN], NE;
     44 bool vis[MAXN];
     45  
     46 void add_edge (int u, int v, int w)
     47 {
     48     E[NE].u = u; E[NE].v = v; E[NE].w = w; E[NE].next = head[u]; head[u] = NE++;
     49     E[NE].u = v; E[NE].v = u; E[NE].w = 0; E[NE].next = head[v]; head[v] = NE++;
     50 }
     51  
     52 inline void checkmin(int &a, int b)  {if(a == -1 || a > b)a = b;}
     53  
     54 int sap(int s,int t)
     55 {
     56     clr(dis); clr(gap);
     57     for(int i=0;i<N;++i) cur[i] = head[i];
     58     int u = pre[s] = s, maxflow = 0, aug = -1;
     59     gap[0] = N;
     60     while(dis[s] < N)
     61     {
     62 loop:for(int &i = cur[u]; i != -1; i = E[i].next)
     63         {
     64             int v = E[i].v;
     65             if(E[i].w && dis[u] == dis[v]+1)
     66             {
     67                 checkmin(aug, E[i].w);
     68                 pre[v] = u;
     69                 u = v;
     70                 if(v == t)
     71                 {
     72                     maxflow += aug;
     73                     for(u = pre[u]; v != s; v = u, u = pre[u])
     74                     {
     75                         E[cur[u]].w -= aug;
     76                         E[cur[u]^1].w += aug;
     77                     }
     78                     aug=-1;
     79                 }
     80                 goto loop;
     81             }
     82         }
     83         int mindis = N;
     84         for(int i = head[u]; i!=-1;i = E[i].next)
     85         {
     86             int v = E[i].v;
     87             if(E[i].w && mindis>dis[v])
     88             {
     89                 cur[u] = i;
     90                 mindis = dis[v];
     91             }
     92         }
     93         if((--gap[dis[u]]) == 0) break;
     94         gap[dis[u]=mindis+1]++;
     95         u = pre[u];
     96     }
     97     return maxflow;
     98 }
     99  
    100 void init()
    101 {
    102     NE = 0; 
    103     memset(head, -1, sizeof head);
    104 }
    105  
    106 int main()
    107 {
    108     int sum, a, b, c;
    109     while(RII(n, m) != EOF)
    110     {
    111         init();
    112         sum = 0;
    113         int s = 0, t = n+m+1;
    114         N = t + 1;
    115         rep(i,1,n)
    116         {
    117             RI(c);
    118             add_edge(i, t, c);
    119         }
    120         rep(i,1,m)
    121         {
    122             RIII(a, b, c);
    123             add_edge(s, i+n, c);
    124             add_edge(i+n, a, oo);
    125             add_edge(i+n, b, oo);
    126             sum += c;
    127         }
    128         printf("%d
    ", sum - sap(s, t));
    129     }
    130     return 0;
    131 }
    View Code

    HDU 3996 Gold Mine

      对于某片矿i,源点向 i 连一条边,权值为收益; i 向汇点连一条边,权值为花费。对于关联的两点,连一条边,权值为无穷大。答案为总收益 - 最小割。

      1 #include <vector>
      2 #include <list>
      3 #include <map>
      4 #include <set>
      5 #include <queue>
      6 #include <deque>
      7 #include <stack>
      8 #include <algorithm>
      9 #include <sstream>
     10 #include <iostream>
     11 #include <iomanip>
     12 #include <cstdio>
     13 #include <cstdlib>
     14 #include <cstring>
     15 #include <cmath>
     16 #include <queue>
     17 using namespace std;
     18 #define pii         pair<int,int>
     19 #define clr(a)      memset((a),0,sizeof (a))
     20 #define rep(i,a,b)  for(int i=(a);i<=(int)(b);i++)
     21 #define per(i,a,b)  for(int i=(a);i>=(int)(b);i--)
     22 #define oo          (1LL)<<60
     23 #define eps         1e-6
     24 #define MAXN        50005
     25 #define MAXM        5000010
     26 #define MOD         1000000007
     27 #define debug       puts("here")
     28 #define MP          make_pair
     29 #define PB          push_back
     30 #define RI(x)       scanf("%d",&x)
     31 #define RII(x,y)    scanf("%d%d",&x,&y)
     32 #define RIII(x,y,z) scanf("%d%d%d",&x,&y,&z)
     33 typedef long long LL;
     34 
     35 struct Edge
     36 {
     37     int u, v, next;
     38     LL w;
     39 }E[MAXM];
     40 
     41 int gap[MAXN], pre[MAXN], cur[MAXN], dis[MAXN];
     42 int n, m, N;
     43 int head[MAXN], NE;
     44 bool vis[MAXN];
     45 int h[105][30];
     46 
     47 void add_edge (int u, int v, LL w)
     48 {
     49     E[NE].u = u; E[NE].v = v; E[NE].w = w; E[NE].next = head[u]; head[u] = NE++;
     50     E[NE].u = v; E[NE].v = u; E[NE].w = 0; E[NE].next = head[v]; head[v] = NE++;
     51 }
     52 
     53 inline void checkmin(LL &a, LL b)  {if(a == -1 || a > b) a = b;}
     54 
     55 LL sap(int s,int t)
     56 {
     57     clr(dis); clr(gap);
     58     for(int i=0;i<N;++i) cur[i] = head[i];
     59     int u = pre[s] = s;
     60     LL maxflow = 0, aug = -1;
     61     gap[0] = N;
     62     while(dis[s] < N)
     63     {
     64 loop:for(int &i = cur[u]; i != -1; i = E[i].next)
     65         {
     66             int v = E[i].v;
     67             if(E[i].w && dis[u] == dis[v]+1)
     68             {
     69                 checkmin(aug, E[i].w);
     70                 pre[v] = u;
     71                 u = v;
     72                 if(v == t)
     73                 {
     74                     maxflow += aug;
     75                     for(u = pre[u]; v != s; v = u, u = pre[u])
     76                     {
     77                         E[cur[u]].w -= aug;
     78                         E[cur[u]^1].w += aug;
     79                     }
     80                     aug=-1;
     81                 }
     82                 goto loop;
     83             }
     84         }
     85         int mindis = N;
     86         for(int i = head[u]; i!=-1;i = E[i].next)
     87         {
     88             int v = E[i].v;
     89             if(E[i].w && mindis>dis[v])
     90             {
     91                 cur[u] = i;
     92                 mindis = dis[v];
     93             }
     94         }
     95         if((--gap[dis[u]]) == 0) break;
     96         gap[dis[u]=mindis+1]++;
     97         u = pre[u];
     98     }
     99     return maxflow;
    100 }
    101 
    102 void init()
    103 {
    104     NE = 0;
    105     memset(head, -1, sizeof head);
    106 }
    107 
    108 int main()
    109 {
    110     int t, a, b, c, src, des, id, cas = 1;
    111     LL sum;
    112     RI(t);
    113     while(t--)
    114     {
    115         RI(n);
    116         init();
    117         src = 0, des = 50000;
    118         id = 0; sum = 0;
    119         rep(i,1,n)
    120         {
    121             RI(m);
    122             rep(j,1,m)
    123             {
    124                 ++id;
    125                 RIII(a,b,c);
    126                 h[i][j] = id;
    127                 sum += b;
    128                 add_edge(src, id, b);
    129                 add_edge(id, des, a);
    130                 rep(k,1,c)
    131                 {
    132                     RII(a, b);
    133                     add_edge(id, h[a][b], oo);
    134                 }
    135             }
    136         }
    137         N = id + 2;
    138         printf("Case #%d: %I64d
    ", cas++, sum - sap(src, des));
    139     }
    140     return 0;
    141 }
    View Code

    CSU 1319 CX's dream

      这道题是zzy师兄出的题目,需要在流网络最大权闭包的基础上求出可获得的最多节点数,对于网络流里获取最多节点数,一般需要加一个偏移量,最后取模就可以了。因为这道题求的是最多实现的梦想,所以对于付出节点,即使其为正数,也不加偏移,只在梦想节点加偏移,最后答案就是“总的梦想数 - 总偏移”。这道题需要用long long。

      1 #include <vector>
      2 #include <list>
      3 #include <map>
      4 #include <set>
      5 #include <queue>
      6 #include <deque>
      7 #include <stack>
      8 #include <algorithm>
      9 #include <sstream>
     10 #include <iostream>
     11 #include <iomanip>
     12 #include <cstdio>
     13 #include <cstdlib>
     14 #include <cstring>
     15 #include <cmath>
     16 #include <queue>
     17 using namespace std;
     18 #define pii         pair<LL,LL>
     19 #define clr(a)      memset((a),0,sizeof (a))
     20 #define rep(i,a,b)  for(LL i=(a);i<=(LL)(b);i++)
     21 #define per(i,a,b)  for(LL i=(a);i>=(LL)(b);i--)
     22 #define oo          ((LL)2000000007)*((LL)2000000007)
     23 #define eps         1e-6
     24 #define MAXN        5005
     25 #define MAXM        2000005
     26 #define MOD         1000000007
     27 #define debug       puts("reach here")
     28 #define MP          make_pair
     29 #define PB          push_back
     30 #define RI(x)       scanf("%lld",&x)
     31 #define RII(x,y)    scanf("%lld%lld",&x,&y)
     32 #define RIII(x,y,z) scanf("%d%d%d",&x,&y,&z)
     33 typedef long long LL;
     34  
     35 struct Edge
     36 {
     37     LL u, v, next;
     38     LL w;
     39 }E[MAXM];     
     40  
     41 LL gap[MAXN], pre[MAXN], cur[MAXN], dis[MAXN];
     42 LL n, m;
     43 LL N;
     44 LL head[MAXN], NE;
     45 bool vis[MAXN];
     46  
     47 void add_edge (LL u, LL v, LL w)
     48 {
     49     E[NE].u = u; E[NE].v = v; E[NE].w = w; E[NE].next = head[u]; head[u] = NE++;
     50     E[NE].u = v; E[NE].v = u; E[NE].w = 0; E[NE].next = head[v]; head[v] = NE++;
     51 }
     52  
     53 inline void checkmin(LL &a,LL b)  {if(a == -1 || a > b)a = b;}
     54  
     55 LL sap(LL s,LL t)
     56 {
     57     clr(dis); clr(gap);
     58     for(LL i=0;i<N;++i) cur[i]=head[i];
     59     LL u=pre[s]=s;
     60     LL maxflow=0;
     61     LL aug=-1;
     62     gap[0]=N;
     63     while(dis[s]<N)
     64     {
     65 loop:for(LL &i=cur[u];i!=-1;i=E[i].next)
     66         {
     67             LL v=E[i].v;
     68             if(E[i].w && dis[u]==dis[v]+1)
     69             {
     70                 checkmin(aug,E[i].w);
     71                 pre[v]=u;
     72                 u=v;
     73                 if(v==t)
     74                 {
     75                     maxflow += aug;
     76                     for(u=pre[u];v!=s;v=u,u=pre[u])
     77                     {
     78                         E[cur[u]].w-=aug;
     79                         E[cur[u]^1].w+=aug;
     80                     }
     81                     aug=-1;
     82                 }
     83                 goto loop;
     84             }
     85         }
     86         LL mindis=N;
     87         for(LL i=head[u];i!=-1;i=E[i].next)
     88         {
     89             LL v=E[i].v;
     90             if(E[i].w && mindis>dis[v])
     91             {
     92                 cur[u]=i;
     93                 mindis=dis[v];
     94             }
     95         }
     96         if((--gap[dis[u]])==0) break;
     97         gap[dis[u]=mindis+1]++;
     98         u=pre[u];
     99     }
    100     return maxflow;
    101 }
    102  
    103 void init()
    104 {
    105     NE = 0; 
    106     memset(head, -1, sizeof head);
    107 }
    108  
    109 int main()
    110 {
    111     LL a, k;
    112     LL sum, v;
    113     LL M = 5000;
    114     while(scanf("%lld%lld", &n, &m) != EOF)
    115     {
    116         init();
    117         LL s = 0, t = n + m + 1;
    118         sum = 0;
    119         N = t + 1;
    120         rep(i,1,n)
    121         {
    122             scanf("%lld", &v);
    123             add_edge(s, i, v*M+1);
    124             sum += v;
    125         }
    126         rep(i,1,m)
    127         {
    128             scanf("%lld", &v);
    129             if(v > 0)
    130             {
    131                 sum += v;
    132                 add_edge(s, i+n, v*M);
    133             }
    134             else
    135                 add_edge(i+n, t, -v*M);
    136         }
    137         rep(i,1,n)
    138         {
    139             scanf("%lld", &k);
    140             rep(j,1,k)
    141             {
    142                 scanf("%lld", &a);
    143                 add_edge(i, a+n, oo);
    144             }
    145         }
    146         LL ans = sap(s, t);
    147        printf("%lld %lld
    ", sum - ans/M, n - (ans%M));
    148     }
    149     return 0;
    150 }
    View Code
  • 相关阅读:
    流畅的python——2 数据结构
    流畅的python——1 数据模型
    cpp3 std::bind
    cpp2 std::forward
    什么是 jQuery EasyUI?
    .Core中什么事依赖注入?
    .net 中datetime? 和 datetime 有什么区别?
    C#生成项目失败 错误列表 CS2001 未能找到源文件 “D:XXXXXX.cs”。
    Docker笔记
    ICollection与IEnumerable
  • 原文地址:https://www.cnblogs.com/huangfeihome/p/3349572.html
Copyright © 2011-2022 走看看