【codevs1922】骑士共存问题——网络流

给棋盘黑白染色,源点向不为障碍的奇点连一条权值为1的边,向可以攻击到的偶点连一条边,权值为inf;偶点向汇点(t=n*n+1)连一条权值为1的边。

跑最小割,最小割的意义就是看至少要放弃几个点(即这里不放骑士)才能使他们不会互相攻击,最后用总格数减去最小割时记得也要减去障碍数,即n*n-ans-m.

具体细节看代码:

#include<cstdio>
#include<cstring>
#include<iostream>
const int inf=0x3f3f3f3f;
using namespace std;
int n,m,s,t;
struct point
{
    int flow,to,next;
}e[500500];
int q[40050],d[40050],tot=1,first[40010],cur[40010];
bool mapp[204][204];
int cc[10][2]={{1,2},{2,1},{-1,2},{-1,-2},{1,-2},{2,-1},{-2,1},{-2,-1}};
void insert(int u,int v,int w)
{
    tot++;e[tot].to=v;e[tot].flow=w;e[tot].next=first[u];first[u]=tot;
    tot++;e[tot].to=u;e[tot].flow=0;e[tot].next=first[v];first[v]=tot;
}
bool bfs()
{
    memset(d,-1,sizeof(d));
    d[0]=0;q[0]=0;
    int head=0,tail=1;
    while(head!=tail)
    {
        int x=q[head++];if(head>=40000)head=0;
        for(int i=first[x];i;i=e[i].next)
        {
            if(d[e[i].to]==-1&&e[i].flow>0)
            {
                d[e[i].to]=d[x]+1;
                q[tail++]=e[i].to;
                if(tail>=40000)tail=0;
            }
        }
    }
    if(d[t]==-1)return false;
    return true;
}
int dfs(int x,int a)
{
    if(x==t||a==0)return a;
    int flow=0,f;
    for(int& i=cur[x];i;i=e[i].next)
    {
        if(d[e[i].to]==d[x]+1&&(f=dfs(e[i].to,min(a,e[i].flow)))>0)
        {
            e[i].flow-=f;
            e[i^1].flow+=f;
            a-=f;
            flow+=f;
            if(!a)break;
        }
    }
    return flow;
}
int sum(int x,int y)
{
    return (x-1)*n+y;
}
int main()
{
    int x,y,ans=0;
    scanf("%d %d",&n,&m);
    s=0;t=n*n+1;
    for(int i=1;i<=m;i++)
    {
        scanf("%d %d",&x,&y);
        mapp[x][y]=1;
    }
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=n;j++)
        {
            if(!mapp[i][j]&&!((i+j)%2))
            {
                insert(s,sum(i,j),1);
                for(int k=0;k<8;k++)
                {
                    int xx=cc[k][0],yy=cc[k][1];
                    if(i+xx>0&&i+xx<=n&&j+yy>0&&j+yy<=n&&!mapp[i+xx][j+yy])insert(sum(i,j),sum(i+xx,j+yy),inf);
                }
            }
            else if(!mapp[i][j])insert(sum(i,j),t,1);
        }
    }
    while(bfs())
    {
        for(int i=0;i<=t;i++)cur[i]=first[i];
        ans+=dfs(0,inf);
    }
    printf("%d\n",n*n-ans-m);
    return 0;
}

时间: 2024-08-09 00:21:46

【codevs1922】骑士共存问题——网络流的相关文章

P3355 骑士共存问题 网络流

骑士共存 题目描述 在一个 n*n个方格的国际象棋棋盘上,马(骑士)可以攻击的棋盘方格如图所示.棋盘上某些方格设置了障碍,骑士不得进入 对于给定的 n*n 个方格的国际象棋棋盘和障碍标志,计算棋盘上最多可以放置多少个骑士,使得它们彼此互不攻击 输入输出格式 输入格式: 第一行有 2 个正整数n 和 m (1<=n<=200, 0<=m<n2),分别表示棋盘的大小和障碍数.接下来的 m 行给出障碍的位置.每行 2 个正整数,表示障碍的方格坐标. 输出格式: 将计算出的共存骑士数输出

[COGS746] [网络流24题] 骑士共存

★★☆   输入文件:knight.in   输出文件:knight.out   简单对比 时间限制:1 s   内存限制:128 MB 骑士共存问题 «问题描述: 在一个n*n个方格的国际象棋棋盘上,马(骑士)可以攻击的棋盘方格如图所示.棋盘 上某些方格设置了障碍,骑士不得进入. «编程任务: 对于给定的n*n个方格的国际象棋棋盘和障碍标志,计算棋盘上最多可以放置多少个骑 士,使得它们彼此互不攻击. «数据输入: 由文件knight.in给出输入数据.第一行有2 个正整数n 和m (1<=n<

AC日记——[网络流24题]骑士共存 cogs 746

746. [网络流24题] 骑士共存 ★★☆   输入文件:knight.in   输出文件:knight.out   简单对比时间限制:1 s   内存限制:128 MB 骑士共存问题 «问题描述: 在一个n*n个方格的国际象棋棋盘上,马(骑士)可以攻击的棋盘方格如图所示.棋盘 上某些方格设置了障碍,骑士不得进入. «编程任务: 对于给定的n*n个方格的国际象棋棋盘和障碍标志,计算棋盘上最多可以放置多少个骑 士,使得它们彼此互不攻击. «数据输入: 由文件knight.in给出输入数据.第一行

[网络流24题] 骑士共存

746. [网络流24题] 骑士共存 ★★☆   输入文件:knight.in   输出文件:knight.out   简单对比 时间限制:1 s   内存限制:128 MB 骑士共存问题 «问题描述: 在一个n*n个方格的国际象棋棋盘上,马(骑士)可以攻击的棋盘方格如图所示.棋盘 上某些方格设置了障碍,骑士不得进入. «编程任务: 对于给定的n*n个方格的国际象棋棋盘和障碍标志,计算棋盘上最多可以放置多少个骑 士,使得它们彼此互不攻击. «数据输入: 由文件knight.in给出输入数据.第一

【wikioi】1922 骑士共存问题(网络流/二分图匹配)

用匈牙利tle啊喂?和网络流不都是n^3的吗.... (更新:what!!!!!!发现个无语的问题,.!!!!结构比数组快啊orz,这节奏不对啊....以后图都写结构的节奏啊... #include <cstdio> #include <cstring> #include <cmath> #include <string> #include <iostream> #include <algorithm> using namespace

【网络流24题】骑士共存问题(最大流)

[网络流24题]骑士共存问题(最大流) 题面 Cogs 题解 这题本质上和方格取数问题没有任何区别 首先也是可以黑白染色 因为马必定会跳到异色点上面去 然后同样的,源点向一种颜色,另一种颜色向汇点连边 因为代价就是1,所以容量都是1 这里考虑的"相邻"的情况是马的跳法 因此,枚举从当前点能够到达的位置,连一条容量为INF的边过去 障碍直接特殊考虑就行了 最后的答案就是所有可以放的位置数减去最大流(最小割) #include<iostream> #include<cst

[网络流24题] 骑士共存(cogs 746)

骑士共存问题?问题描述:在一个n*n个方格的国际象棋棋盘上,马(骑士)可以攻击的棋盘方格如图所示.棋盘 上某些方格设置了障碍,骑士不得进入. ?编程任务:对于给定的n*n个方格的国际象棋棋盘和障碍标志,计算棋盘上最多可以放置多少个骑士,使得它们彼此互不攻击.?数据输入:由文件knight.in给出输入数据.第一行有2 个正整数n 和m (1<=n<=200, 0<=m<=n*n)<n2),< span="">分别表示棋盘的大小和障碍数.接下来的

P3355 骑士共存问题 二分建图 + 当前弧优化dinic

P3355 骑士共存问题 题意: 也是一个棋盘,规则是“马”不能相互打到. 思路: 奇偶点分开,二分图建图,这道题要注意每个点可以跑八个方向,两边都可以跑,所以边 = 20 * n * n. 然后dinic 要用当前弧优化. #include <algorithm> #include <iterator> #include <iostream> #include <cstring> #include <cstdlib> #include <

【Codevs1922】骑士共存问题(最小割,二分图最大匹配)

题意: 在一个n*n个方格的国际象棋棋盘上,马(骑士)可以攻击的棋盘方格如图所示.棋盘上某些方格设置了障碍,骑士不得进入. 对于给定的n*n个方格的国际象棋棋盘和障碍标志,计算棋盘上最多可以放置多少个骑士,使得它们彼此互不攻击. n<=200,m<=n^2 思路:经典的二分图最大匹配问题,采用黑白点染色的思想. 如果按照相邻点黑白不同染色,可以发现每次跳到的点必定与现在所在点不同色,二分图最大匹配即可. 这里用最小割来解决,因为不能允许任何黑白点之间的任何一条边有流量,符合最小割的思想. 1