[BZOJ4808] 马(最大独立集,最大流)

Posted tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[BZOJ4808] 马(最大独立集,最大流)相关的知识,希望对你有一定的参考价值。

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=4808

题意:其实就是找出一个点集的子集,使得这个子集中的点互不相连。求这个子集规模最大。

就是最大独立集。点好多,有200*200个。所以用dinic优化了下。

最大独立集=N-最大匹配,最大匹配=最大流,所以最大独立集=N-最大流。

  1 #include <bits/stdc++.h>
  2 using namespace std;
  3 
  4 //下标从0开始
  5 typedef struct Edge {
  6     int u, v, w, next;
  7 }Edge;
  8 
  9 const int inf = 0x7f7f7f7f;
 10 const int maxn = 400400;
 11 const int maxm = 220;
 12 
 13 int cnt, dhead[maxn];
 14 int cur[maxn], dd[maxn];
 15 Edge dedge[maxn<<1];
 16 // bool vis[maxn]; // 记录经过的点
 17 int S, T, N;
 18 
 19 void init() {
 20     memset(dhead, -1, sizeof(dhead));
 21     for(int i = 0; i < maxn; i++) dedge[i].next = -1;
 22     S = 0; cnt = 0;
 23 }
 24 
 25 void adde(int u, int v, int w, int c1=0) {
 26     dedge[cnt].u = u; dedge[cnt].v = v; dedge[cnt].w = w; 
 27     dedge[cnt].next = dhead[u]; dhead[u] = cnt++;
 28     dedge[cnt].u = v; dedge[cnt].v = u; dedge[cnt].w = c1; 
 29     dedge[cnt].next = dhead[v]; dhead[v] = cnt++;
 30 }
 31 
 32 bool bfs(int s, int t, int n) {
 33     // memset(vis, 0, sizeof(vis));
 34     queue<int> q;
 35     for(int i = 0; i < n; i++) dd[i] = inf;
 36     dd[s] = 0;
 37     q.push(s);
 38     while(!q.empty()) {
 39         int u = q.front(); q.pop();
 40         for(int i = dhead[u]; ~i; i = dedge[i].next) {
 41             if(dd[dedge[i].v] > dd[u] + 1 && dedge[i].w > 0) {
 42                 dd[dedge[i].v] = dd[u] + 1;
 43                 // vis[dedge[i].v] = 1;
 44                 if(dedge[i].v == t) return 1;
 45                 q.push(dedge[i].v);
 46             }
 47         }
 48     }
 49     return 0;
 50 }
 51 
 52 int dinic(int s, int t, int n) {
 53     int st[maxn], top;
 54     int u;
 55     int flow = 0;
 56     while(bfs(s, t, n)) {
 57         for(int i = 0; i < n; i++) cur[i] = dhead[i];
 58         u = s; top = 0;
 59         while(cur[s] != -1) {
 60             if(u == t) {
 61                 int tp = inf;
 62                 for(int i = top - 1; i >= 0; i--) {
 63                     tp = min(tp, dedge[st[i]].w);
 64                 }
 65                 flow += tp;
 66                 for(int i = top - 1; i >= 0; i--) {
 67                     dedge[st[i]].w -= tp;
 68                     dedge[st[i] ^ 1].w += tp;
 69                     if(dedge[st[i]].w == 0) top = i;
 70                 }
 71                 u = dedge[st[top]].u;
 72             }
 73             else if(cur[u] != -1 && dedge[cur[u]].w > 0 && dd[u] + 1 == dd[dedge[cur[u]].v]) {
 74                 st[top++] = cur[u];
 75                 u = dedge[cur[u]].v;
 76             }
 77             else {
 78                 while(u != s && cur[u] == -1) {
 79                     u = dedge[st[--top]].u;
 80                 }
 81                 cur[u] = dedge[cur[u]].next;
 82             }
 83         }
 84     }
 85     return flow;
 86 }
 87 
 88 const int dx[11] = {-1,1,2,2,1,-1,-2,-2};
 89 const int dy[11] = {-2,-2,-1,1,2,2,1,-1};
 90 int n, m;
 91 int mp[maxm][maxm];
 92 
 93 inline bool bound(int x, int y) { return x >= 1 && x <= n && y >= 1 && y <= m;}
 94 inline int id(int x, int y) { return (x - 1) * m + y; }
 95 
 96 int main() {
 97     // freopen("in", "r", stdin);
 98     while(~scanf("%d%d",&n,&m)) {
 99         init();
100         S = 0, T = 2 * id(n, m) + 1, N = T + 1;
101         for(int i = 1; i <= n; i++) {
102             for(int j = 1; j <= m; j++) {
103                 adde(S, id(i,j), 1);
104                 adde(id(n,m)+id(i,j), T, 1);
105                 scanf("%d", &mp[i][j]);
106             }
107         }
108         int tot = 0;
109         for(int i = 1; i <= n; i++) {
110             for(int j = 1; j <= m; j++) {
111                 if(mp[i][j] == 1) continue;
112                 tot++;
113                 for(int k = 0; k < 8; k++) {
114                     int x = i + dx[k];
115                     int y = j + dy[k];
116                     if(!bound(x, y)) continue;
117                     if(!mp[x][y]) adde(id(i,j), id(n,m)+id(x,y), inf);
118                 }
119             }
120         }
121         printf("%d\n", tot - dinic(S, T, N)/2);
122     }
123     return 0;
124 }

 

以上是关于[BZOJ4808] 马(最大独立集,最大流)的主要内容,如果未能解决你的问题,请参考以下文章

BZOJ-4808: 马 (二分图最大独立集 WAing~)

BZOJ 4808 二分图最大独立集

bzoj3175: [Tjoi2013]攻击装置&&4808: 马

bzoj4808: 马 & bzoj3175: [Tjoi2013]攻击装置 (黑白染色+最小割)

BZOJ 1143: [CTSC2008]祭祀river 最大独立集

BZOJ4808: 马&BZOJ3175: [Tjoi2013]攻击装置