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
  • 相关阅读:
    Apache 虚拟主机 VirtualHost 配置
    EAX、ECX、EDX、EBX寄存器的作用
    Python中文文档 目录(转载)
    八度
    POJ 3268 Silver Cow Party (最短路)
    POJ 2253 Frogger (求每条路径中最大值的最小值,Dijkstra变形)
    2013金山西山居创意游戏程序挑战赛——复赛(1) HDU 4557 非诚勿扰 HDU 4558 剑侠情缘 HDU 4559 涂色游戏 HDU 4560 我是歌手
    HDU 4549 M斐波那契数列(矩阵快速幂+欧拉定理)
    UVA 11624 Fire! (简单图论基础)
    HDU 3534 Tree (树形DP)
  • 原文地址:https://www.cnblogs.com/lwqq3/p/11161143.html
Copyright © 2011-2022 走看看