zoukankan      html  css  js  c++  java
  • [TJOI2013] 攻击装置

    给定 (N imes N) 棋盘,某些格子是障碍,问可以放置的互不侵犯的马的个数

    黑白染色后建立二分图,求最大独立集 = 总点数 - 最大匹配数

    注意把反边也连上会WA掉(脑抽一发血)

    #include <bits/stdc++.h>
    using namespace std;
    
    // Input: make(u,v,w)
    // Solver: int solve(s,t);
    // Output: ans(returned)
    namespace flow {
    
    const int maxn = 300005;
    const int inf = 1e+9;
    
    int dis[maxn], ans, cnt = 1, s, t, pre[maxn * 10], nxt[maxn * 10], h[maxn], v[maxn * 10];
    std::queue<int> q;
    void make(int x, int y, int z) {
        pre[++cnt] = y, nxt[cnt] = h[x], h[x] = cnt, v[cnt] = z;
        pre[++cnt] = x, nxt[cnt] = h[y], h[y] = cnt;
    }
    bool bfs() {
        memset(dis, 0, sizeof dis);
        q.push(s), dis[s] = 1;
        while (!q.empty()) {
            int x = q.front();
            q.pop();
            for (int i = h[x]; i; i = nxt[i])
                if (!dis[pre[i]] && v[i])
                    dis[pre[i]] = dis[x] + 1, q.push(pre[i]);
        }
        return dis[t];
    }
    int dfs(int x, int flow) {
        if (x == t || !flow)
            return flow;
        int f = flow;
        for (int i = h[x]; i; i = nxt[i])
            if (v[i] && dis[pre[i]] > dis[x]) {
                int y = dfs(pre[i], min(v[i], f));
                f -= y, v[i] -= y, v[i ^ 1] += y;
                if (!f)
                    return flow;
            }
        if (f == flow)
            dis[x] = -1;
        return flow - f;
    }
    int solve(int _s,int _t) {
        s=_s;
        t=_t;
        ans = 0;
        for (; bfs(); ans += dfs(s, inf));
        return ans;
    }
    }
    
    int n,cnt;
    char s[205][205];
    
    const int dx[9]={0,1,1,-1,-1,2,2,-2,-2};
    const int dy[9]={0,2,-2,2,-2,1,-1,1,-1};
    
    int check(int i,int j) {
        if(i>0 && j>0 && i<=n && j<=n && s[i][j]=='0') return 1;
        return 0;
    }
    
    int main() {
        cin>>n;
        for(int i=1;i<=n;i++) cin>>s[i]+1;
        for(int i=1;i<=n;i++) {
            for(int j=1;j<=n;j++) {
                if(check(i,j)) {
                    ++cnt;
                    if((i+j)&1) flow::make(n*n+1,i*n-n+j,1);
                    else flow::make(i*n-n+j,n*n+2,1);
                }
                if((i+j)&1) for(int k=1;k<=8;k++) {
                    int p=i+dx[k],q=j+dy[k];
                    if(check(i,j) && check(p,q)) {
                        flow::make(i*n-n+j,p*n-n+q,1);
                    }
                }
            }
        }
        cout<<cnt-flow::solve(n*n+1,n*n+2);
    }
    
  • 相关阅读:
    pku2351 Colored Sticks
    JSOI2010 满汉全席
    享元模式
    适配器模式
    合成模式
    原型模式
    创建型设计模式
    建造者模式
    装饰模式
    单例模式
  • 原文地址:https://www.cnblogs.com/mollnn/p/12293924.html
Copyright © 2011-2022 走看看