zoukankan      html  css  js  c++  java
  • [luoguP3355] 骑士共存问题(二分图最大独立集)

    传送门

    模型

    二分图最大独立集,转化为二分图最大匹配,从而用最大流解决。

    实现

    首先把棋盘黑白染色,使相邻格子颜色不同。

    把所有可用的黑色格子看做二分图X集合中顶点,可用的白色格子看做Y集合顶点。

    建立附加源S汇T,从S向X集合中每个顶点连接一条容量为1的有向边,从Y集合中每个顶点向T连接一条容量为1的有向边。

    从每个可用的黑色格子向骑士一步能攻击到的可用的白色格子连接一条容量为无穷大的有向边。

    求出网络最大流,要求的结果就是可用格子的数量减去最大流量。

    分析

    用网络流的方法解决棋盘上的问题,一般都要对棋盘黑白染色,使之成为一个二分图。放尽可能多的不能互相攻击的骑士,就是一个二分图最大独立集问题。有关二分图最大独立集问题,更多讨论见《最小割模型在信息学竞赛中的应用》作者胡伯涛。

    该题规模比较大,需要用效率较高的网络最大流算法解决。(使用Dinic+当前弧优化)

    ——代码

      1 #include <queue>
      2 #include <cstdio>
      3 #include <cstring>
      4 #include <iostream>
      5 #define INF 1e9
      6 #define N 1000001
      7 #define min(x, y) ((x) < (y) ? (x) : (y))
      8 
      9 int n, m, cnt, tot, sum, s, t;
     10 int map[201][201], head[N], to[N], val[N], next[N], dis[N], cur[N];
     11 int dx[8] = {-2, -1, 1, 2, 2, 1, -1, -2},
     12     dy[8] = {1, 2, 2, 1, -1, -2, -2, -1};
     13 
     14 inline int read()
     15 {
     16     int x = 0, f = 1;
     17     char ch = getchar();
     18     for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = -1;
     19     for(; isdigit(ch); ch = getchar()) x = (x << 1) + (x << 3) + ch - '0';
     20     return x * f;
     21 }
     22 
     23 inline void add2(int x, int y, int z)
     24 {
     25     to[cnt] = y;
     26     val[cnt] = z;
     27     next[cnt] = head[x];
     28     head[x] = cnt++;
     29 }
     30 
     31 inline void add(int x, int y, int z)
     32 {
     33     add2(x, y, z);
     34     add2(y, x, 0);
     35 }
     36 
     37 inline bool bfs()
     38 {
     39     int i, u, v;
     40     std::queue <int> q;
     41     memset(dis, -1, sizeof(dis));
     42     q.push(s);
     43     dis[s] = 0;
     44     while(!q.empty())
     45     {
     46         u = q.front(), q.pop();
     47         for(i = head[u]; i ^ -1; i = next[i])
     48         {
     49             v = to[i];
     50             if(val[i] && dis[v] == -1)
     51             {
     52                 dis[v] = dis[u] + 1;
     53                 if(v == t) return 1;
     54                 q.push(v);
     55             }
     56         }
     57     }
     58     return 0;
     59 }
     60 
     61 inline int dfs(int u, int maxflow)
     62 {
     63     if(u == t) return maxflow;
     64     int v, d, ret = 0;
     65     for(int &i = cur[u]; i ^ -1; i = next[i])
     66     {
     67         v = to[i];
     68         if(val[i] && dis[v] == dis[u] + 1)
     69         {
     70             d = dfs(v, min(val[i], maxflow - ret));
     71             ret += d;
     72             val[i] -= d;
     73             val[i ^ 1] += d;
     74             if(ret == maxflow) return ret;
     75         }
     76     }
     77     return ret;
     78 }
     79 
     80 int main()
     81 {
     82     int i, j, k, x, y;
     83     n = read();
     84     m = read();
     85     s = 0, t = n * n + 1;
     86     memset(head, -1, sizeof(head));
     87     for(i = 1; i <= m; i++)
     88     {
     89         x = read();
     90         y = read();
     91         map[x][y] = -1;
     92     }
     93     for(i = 1; i <= n; i++)
     94         for(j = 1; j <= n; j++)
     95             if(!map[i][j])
     96             {
     97                 map[i][j] = ++tot;
     98                 if((i + j) & 1) add(s, tot, 1);
     99                 else add(tot, t, 1);
    100             }
    101     for(i = 1; i <= n; i++)
    102         for(j = 1; j <= n; j++)
    103             if(map[i][j] ^ -1 && (i + j) & 1)
    104                 for(k = 0; k < 8; k++)
    105                 {
    106                     x = i + dx[k];
    107                     y = j + dy[k];
    108                     if(x >= 1 && x <= n && y >= 1 && y <= n && map[x][y] ^ -1) add(map[i][j], map[x][y], INF);
    109                 }
    110     while(bfs())
    111     {
    112         for(i = s; i <= t; i++) cur[i] = head[i];
    113         sum += dfs(s, INF);
    114     }
    115     printf("%d
    ", tot - sum);
    116     return 0;
    117 }
    View Code
  • 相关阅读:
    RSA加密
    各种正则
    用Fragment制作的Tab页面产生的UI重叠问题
    Android源码下载
    Android Studio使用百度地图问题总结
    Android获取网络类型
    Android Studio类中实现Serializable自动生成serialVersionUID
    【Android开发】如何设计开发一款Android App
    UIViewController生命周期
    微信支付开发经验分享
  • 原文地址:https://www.cnblogs.com/zhenghaotian/p/7010407.html
Copyright © 2011-2022 走看看