题意:略
分析:
黑白棋盘,转化为二分图。
1、最大点权独立集 = sum - 最小点权覆盖集
2、最小点权覆盖集 = 最小割 = 最大流
3、贴了个dinic模板
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
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 }
开始刷 网络流!