hdu3061 Battle(最大权闭合图)

Amber的论文《最小割模型在信息学竞赛中的应用》

【最大权闭合图】定义一个有向图G=(V,E)的闭合图,是该有向图的一个点集,且该点集所有出边都还指向该点集。即闭合图内的任意点的任意后继也一定在闭合图中。

【建图】源点向正权点加边,容量为权值;负权点向汇点加边,容量为权的绝对值;有限制关系的点加边,容量为INF。

【定理】最大权闭合图 = 正权值和 - 最小割

  1 #include<stdio.h>
  2 #include<string.h>
  3 #include<math.h>
  4 #include<algorithm>
  5 
  6 using namespace std;
  7 
  8 #define INF 1e8
  9 #define MAX_VECT 505
 10 #define MAX_EDGE 220000
 11 
 12 /************************************************************************/
 13 /*    Name: dinic
 14 /*  Description: Find the max flow of the network from start to
 15                  end point
 16 /*  Variable Description: to[] - end point of the current edge
 17                           next[] - the next edge which also comes from
 18                                    the same point as current edge
 19                           cap[] - the capability of the current edge
 20                           v[] - the first edge index which comes from the
 21                                 the current point
 22                           d[] - the layer number of current point
 23 /************************************************************************/
 24 
 25 
 26 int to[MAX_EDGE], next[MAX_EDGE], cap[MAX_EDGE], tot;
 27 int v[MAX_VECT], d[MAX_VECT], queue[MAX_VECT], n;
 28 int S, T;
 29 inline void single_insert(int _u, int _v, int var)
 30 {
 31     to[tot] = _v;
 32     cap[tot] = var;
 33     next[tot] = v[_u];
 34     v[_u] = tot++;
 35 }
 36 
 37 void insert(int from, int to,  int cap)
 38 {
 39     single_insert(from, to, cap);
 40     single_insert(to, from, 0);
 41 }
 42 
 43 bool bfs_initial()
 44 {
 45     memset(d, -1, sizeof(d));
 46     int bg, ed, x, y;
 47     bg = ed = d[S] = 0;
 48     queue[ed++] = S;
 49     while (bg < ed)
 50     {
 51         x = queue[bg++];
 52         for (int i = v[x]; i+1; i = next[i])
 53         {
 54             y = to[i];
 55             if (cap[i] && d[y] == -1)
 56             {
 57                 d[y] = d[x] + 1;
 58                 if (y == T) return true;
 59                 queue[ed++] = y;
 60             }
 61         }
 62     }
 63     return false;
 64 }
 65 
 66 int Find(int x, int low = INF)
 67 {
 68     if (x == T) return low;
 69     int ret, y, ans = 0;
 70     for (int i = v[x]; (i+1) && low; i = next[i])
 71     {
 72         y = to[i];
 73         if (cap[i] && d[y] == d[x] + 1 && (ret = Find(y, min(low, cap[i]))))
 74         {
 75             cap[i] -= ret;
 76             cap[i^1] += ret;
 77             low -= ret;
 78             ans += ret;
 79         }
 80     }
 81     return ans;
 82 }
 83 int dinic()
 84 {
 85     int ans = 0;
 86     while (bfs_initial())
 87         ans += Find(S);
 88     return ans;
 89 }
 90 
 91 
 92 int dinicc()
 93 {
 94     int ans = 0;
 95     while(bfs_initial())
 96     {
 97         int edge, x, y, back, iter = 1;
 98         while(iter)
 99         {
100             x = (iter == 1) ? S : to[queue[iter - 1]];
101             if (x == T)
102             {
103                 int minE, minCap = INF;
104                 for (int i = 1; i < iter; i++)
105                 {
106                     edge = queue[i];
107                     if (cap[edge] < minCap)
108                     {
109                         minCap = cap[edge];
110                         back = i;
111                     }
112                 }
113                 for (int i = 1; i < iter; i++)
114                 {
115                     edge = queue[i];
116                     cap[edge] -= minCap;
117                     cap[edge ^ 1] += minCap;
118                 }
119                 ans += minCap;
120                 iter = back;
121             }
122             else
123             {
124                 for (edge = v[x]; edge + 1; edge = next[edge])
125                 {
126                     y = to[edge];
127                     if (cap[edge] && d[y] == d[x] + 1)
128                         break;
129                 }
130                 if (edge+1)
131                     queue[iter++] = edge;
132                 else
133                 {
134                     d[x] = -1;
135                     iter--;
136                 }
137             }
138         }
139     }
140     return ans;
141 }
142 int m;
143 int seq[MAX_VECT];
144 int main()
145 {
146     while (scanf("%d%d",&n,&m)==2)
147     {
148         tot = 0;
149         memset(v,-1,sizeof(v));
150         int sum = 0;
151         S = 0;
152         T = n+1;
153         for (int i=1;i<=n;i++)
154         {
155             scanf("%d",&seq[i]);
156             if (seq[i] > 0){
157                 sum += seq[i];
158                 insert(S,i,seq[i]);
159             }else{
160                 insert(i,T,-seq[i]);
161             }
162         }
163         for (int i=1;i<=m;i++)
164         {
165             int u,v;
166             scanf("%d%d",&u,&v);
167             insert(u,v,INF);
168         }
169 
170         int ans = sum - dinic();
171         printf("%d\n",ans);
172     }
173     return 0;
174 }
hdu3061

 

转载于:https://www.cnblogs.com/wangsouc/articles/3296459.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值