zoukankan      html  css  js  c++  java
  • P3355 骑士共存问题 网络流

      

    在一个 n*n个方格的国际象棋棋盘上,马(骑士)可以攻击的棋盘方格如图所示。棋盘上某些方格设置了障碍,骑士不得进入

    对于给定的 n*n 个方格的国际象棋棋盘和障碍标志,计算棋盘上最多可以放置多少个骑士,使得它们彼此互不攻击

    和方格取数一模一样  

    只不过相邻改成了日字  所有的权值都为1 

    主要要减去m个障碍

    #include<bits/stdc++.h>
    using namespace std;
    //input by bxd
    #define rep(i,a,b) for(int i=(a);i<=(b);i++)
    #define repp(i,a,b) for(int i=(a);i>=(b);--i)
    #define RI(n) scanf("%d",&(n))
    #define RII(n,m) scanf("%d%d",&n,&m)
    #define RIII(n,m,k) scanf("%d%d%d",&n,&m,&k)
    #define RS(s) scanf("%s",s);
    #define ll long long
    #define pb push_back
    #define REP(i,N)  for(int i=0;i<(N);i++)
    #define CLR(A,v)  memset(A,v,sizeof A)
    //////////////////////////////////
    #define inf 0x3f3f3f3f
    const int N=4e5+44; 
    const int M=4e6+54;
    
    struct edge {
        int to, next, w;
    } e[M << 1];
    int head[N], cnt = 1;
    void add(int x, int y, int z) {
        e[++cnt] = (edge){y, head[x], z};
        head[x] = cnt;
        e[++cnt] = (edge){x, head[y], 0};
        head[y] = cnt;
    }
    int level[N];
    bool bfs(int s, int t) {
        memset(level, 0, sizeof level);
        queue<int> q;
        level[s] = 1;
        q.push(s);
        while (!q.empty()) {
            int pos = q.front();
            q.pop();
            for (int i = head[pos]; i; i = e[i].next) {
                int nx = e[i].to;
                if (!e[i].w || level[nx]) continue;
                level[nx] = level[pos] + 1;
                q.push(nx);
            }
        }
        return level[t];
    }
    int dfs(int s, int t, int flow) {
        if (s == t) return flow;
        int ret = 0;
        for (int i = head[s]; flow && i; i = e[i].next) {
            int nx = e[i].to;
            if (level[nx] == level[s] + 1 && e[i].w) {
                int tmp = dfs(nx, t, min(flow, e[i].w));
                e[i].w -= tmp;
                e[i ^ 1].w += tmp;
                flow -= tmp;
                ret += tmp;
            }
        }
        if (!ret) level[s] = 0;
        return ret;
    }
    int dinic(int s, int t) {
        int ret = 0;
        while (bfs(s, t)) ret += dfs(s, t, inf);
        return ret;
    }
    
    
    int n,m,s,t;
    int id(int x,int y)
    {
        return (x-1)*n+y+3;
    }
    int mp[205][205];
    int dx[]={1,1,-1,-1,2,2,-2,-2};
    int dy[]={2,-2,2,-2,1,-1,1,-1};
    int main()
    {
        s=1;t=2;
        RII(n,m);
        rep(i,1,m)
        {
            int a,b;RII(a,b);mp[a][b]=1;
        }
        rep(i,1,n)
        rep(j,1,n)
        if(!mp[i][j])
        {
            if((i+j)&1)
            {
                add(s,id(i,j),1);
                rep(k,0,7)
                {
                    int x=i+dx[k],y=j+dy[k];
                    if(x>=1&&x<=n&&y>=1&&y<=n&&mp[x][y]!=1)
                    {
                        add(id(i,j),id(x,y),1);
                    }
                }
            }
            else add(id(i,j),t,1);
        }
        cout<<n*n-m-dinic(s,t);
    }
    View Code

    也可以用二分图匹配来做  但是 会T一些点 (只是介绍思路)

    求的是最大独立集团点数  = n - 最大匹配数!

    #include <bits/stdc++.h>
    using namespace std;
    const int N = 206;
    const int dx[8] = {-2,-2,-1,-1,1,1,2,2};
    const int dy[8] = {-1,1,-2,2,-2,2,-1,1};
    int n, m, ans, f[N][N][2];
    bool a[N][N], v[N][N];
    
    inline bool dfs(int x, int y) {
        for (int i = 0; i < 8; i++) {
            int nx = x + dx[i], ny = y + dy[i];
            if (nx < 1 || ny < 1 || nx > n || ny > n) continue;
            if (a[nx][ny] || v[nx][ny]) continue;
            v[nx][ny] = 1;
            if (!f[nx][ny][0] || dfs(f[nx][ny][0], f[nx][ny][1])) {
                f[nx][ny][0] = x;
                f[nx][ny][1] = y;
                return 1;
            }
        }
        return 0;
    }
    
    int main() {
        cin >> n >> m;
        for (int i = 1; i <= m; i++) {
            int x, y;
            scanf("%d %d", &x, &y);
            a[x][y] = 1;
        }
        for (int i = 1; i <= n; i++)
            for (int j = 1; j <= n; j++) {
                if (((i ^ j) & 1) || a[i][j]) continue;
                memset(v, 0, sizeof(v));
                ans += dfs(i, j);
            }
        cout << n * n - m - ans << endl;
        return 0;
    }
    View Code
  • 相关阅读:
    Poj2155Matrix二维线段树
    二维树状数组模板
    PAT-1014 Waiting in Line (30 分) 优先队列
    PAT-1012 The Best Rank (25 分) 查询分数对应排名(包括并列)
    PAT-1003 Emergency (25 分) 最短路最大点权+求相同cost最短路的数量
    PAT-1001 A+B Format (20 分) 注意零的特例
    利用requests和BeautifulSoup爬取菜鸟教程的代码与图片并保存为markdown格式
    菜鸟教程上的设计模式代码合集
    用python将项目中的所有代码(或txt)合并在一个文件中
    POJ 2485 Prim 找最长的边
  • 原文地址:https://www.cnblogs.com/bxd123/p/10931665.html
Copyright © 2011-2022 走看看