zoukankan      html  css  js  c++  java
  • P3355 骑士共存问题 (最小割)

    题意:nxn的棋盘 有m个坏点 求能在棋盘上放多少个马不会互相攻击

    题解:这个题仔细想想居然和方格取数是一样的!!!

       每个马他能攻击到的地方的坐标 (x+y)奇偶性不一样 于是就黑白染色

       s->黑 白->t

       按条件连黑->白 跑最小割 = 最大流 

       感性理解一下 就是先把所有的点都放上 得到最大的收益

       然后删掉一些点使得合法 删掉一个黑点 减去黑点的收益 和黑点相连的白点受到的束缚就减少了

       如果s和t点能联通的话 表示还有黑点和白点连通 问题就转化为了最小割

    #include <bits/stdc++.h>
    using namespace std;
    const int INF = 0x3f3f3f3f;
    int n, m, s, t, cnt, maxflow;
    int broke[205][205];
    
    struct node {
        int to, nex, val;
    }E[400005];
    int head[40005];
    int cur[40005];
    int dx[] = {-1, -1, 1, 1, -2, -2, 2, 2};
    int dy[] = {2, -2, 2, -2, 1, -1, 1, -1};
    
    void addedge(int x, int y, int va) {
        E[++cnt].to = y; E[cnt].nex = head[x]; head[x] = cnt; E[cnt].val = va;
        E[++cnt].to = x; E[cnt].nex = head[y]; head[y] = cnt; E[cnt].val = 0;
    }
    
    int dep[40005];
    int inque[40005];
    bool bfs() {
        for(int i = 0; i <= t; i++) dep[i] = INF, inque[i] = 0, cur[i] = head[i];
        queue<int> que;
        dep[s] = 0; inque[s] = 1;
        que.push(s);
    
        while(!que.empty()) {
            int u = que.front();
            que.pop();
            inque[u] = 0;
    
            for(int i = head[u]; i; i = E[i].nex) {
                int v = E[i].to;
                if(E[i].val > 0 && dep[v] > dep[u] + 1) {
                    dep[v] = dep[u] + 1;
                    if(!inque[v]) {
                        que.push(v);
                        inque[v] = 1;
                    }
                }
            }
        }
        if(dep[t] != INF) return true;
        return false;
    }
    
    int vis;
    int dfs(int x, int flow) {
        if(x == t) {
            vis = 1;
            maxflow += flow;
            return flow;
        }
    
        int used = 0;
        int rflow = 0;
        for(int i = cur[x]; i; i = E[i].nex) {
            cur[x] = i;
            int v = E[i].to;
            if(E[i].val > 0 && dep[v] == dep[x] + 1) {
                if(rflow = dfs(v, min(flow - used, E[i].val))) {
                    used += rflow;
                    E[i].val -= rflow;
                    E[i ^ 1].val += rflow;
                    if(used == flow) break;
                }
            }
        }
        return used;
    }
    
    void dinic() {
        maxflow = 0;
        while(bfs()) {
            vis = 1;
            while(vis) {
                vis = 0;
                dfs(s, INF);
            }
        }
    }
    
    int id(int x, int y) {
        return (x - 1) * n + y;
    }
    
    bool check(int x, int y) {
        if(x >= 1 && x <= n && y >= 1 && y <= n) return true;
        return false;
    }
    
    int main() {
        cnt = 1;
        scanf("%d%d", &n, &m);
        s = 0;
        t = n * n + 1;
    
        for(int i = 1; i <= m; i++) {
            int x, y; scanf("%d%d", &x, &y);
            broke[x][y] = 1;
        }
        for(int i = 1; i <= n; i++) {
            for(int j = 1; j <= n; j++) {
                int ii = id(i, j);
                if(broke[i][j]) continue;
    
                if((i + j) % 2 != 1) {
                    addedge(s, ii, 1);
                    for(int k = 0; k < 8; k++) {
                        int ax = i + dx[k];
                        int ay = j + dy[k];
                        if(check(ax, ay) && !broke[ax][ay]) addedge(ii, id(ax, ay), INF);
                    }
                } else addedge(ii, t, 1);
            }
        }
        dinic();
        printf("%d
    ", n * n - m - maxflow);
        return 0;
    }
    View Code
  • 相关阅读:
    python CST中国标准时间格式转换
    pytest+报告插件
    getopt实现命令行
    初识Redis
    python list 切片及翻转的使用
    mysql中information_schema表
    获取两个字符串中最长的相同子串
    mongodb数据库备份
    VS2005下边不能使用target>remote tool解决方法
    wince LoadDriver tool
  • 原文地址:https://www.cnblogs.com/lwqq3/p/11161143.html
Copyright © 2011-2022 走看看