HDU 1569 方格取数(2)(最大点权独立集 :最大流)

题意:略

分析:

黑白棋盘,转化为二分图。

1、最大点权独立集 = sum - 最小点权覆盖集

2、最小点权覆盖集 = 最小割 = 最大流

3、贴了个dinic模板

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

 

 

开始刷 网络流!

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值