• [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
    ", tot - dinic(S, T, N)/2);
    122     }
    123     return 0;
    124 }
  • 相关阅读:
    贴板子系列_1-km算法,匈牙利算法
    bzoj 2333
    bzoj 3531 旅行
    斯坦纳树
    可持久化线段树
    下界最小费用最大流
    我们还是太NAive
    ubuntu出现有线已连接却无法上网
    python小爬虫【1】
    [解答]对‘’未定义的引用 collect2: 错误: ld 返回 1
  • 原文地址:https://www.cnblogs.com/kirai/p/6945453.html
Copyright © 2020-2023  润新知