列表

详情


NC213835. [网络流24题]骑士共存问题

描述

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

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

输入描述

第一行有2 个正整数n 和m (1<=n<=200, 0<=m<n^2),分别表示棋盘的大小和障碍数。接下来的m 行给出障碍的位置。每行2 个正整数,表示障碍的方格坐标。

输出描述

将计算出的共存骑士数输出

示例1

输入:

3 2
1 1
3 3

输出:

5

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++(clang++ 11.0.1) 解法, 执行用时: 91ms, 内存消耗: 5652K, 提交时间: 2022-09-07 21:33:41

#include<bits/stdc++.h>
using namespace std ;

const int N = 40005, M = 1e6 + 5, INF = 2147483647 ;
struct Edge
{
    int nxt,to,c ;
}e[M] ;
int head[N],now[N],d[N],tot=1 ;
int S,T ;
queue<int>q ;
void add(int from,int to,int c)
{
    e[++tot].to=to ; e[tot].c=c ; e[tot].nxt=head[from] ; head[from]=tot ;
    e[++tot].to=from ; e[tot].c=0 ; e[tot].nxt=head[to] ; head[to]=tot ;
}
bool bfs()
{
    memset(d,0,sizeof(d)) ;
    while(!q.empty()) q.pop() ;
    q.push(S) ; d[S]=1 ; now[S]=head[S] ;
    while(!q.empty())
    {
        int x=q.front() ; q.pop() ;
        for(int i=head[x];i;i=e[i].nxt)
        {
            int y=e[i].to ;
            if(e[i].c&&!d[y])
            {
                q.push(y) ;
                now[y]=head[y] ;
                d[y]=d[x]+1 ;
                if(y==T) return 1 ;
            }
        }
    }
    return 0 ;
}
int dinic(int x,int flow)
{
    if(x==T) return flow ;
    int rest=flow,k ;
    for(int i=now[x];i&&rest;i=e[i].nxt)
    {
        int y=e[i].to ;
        now[x]=i ;
        if(e[i].c&&d[y]==d[x]+1)
        {
            k=dinic(y,min(e[i].c,rest)) ;
            if(!k) d[y]=0 ;
            e[i].c-=k ;
            e[i^1].c+=k ;
            rest-=k ;
        }
    }
    return flow-rest ;
}
//主函数
int n,m ;
bool a[N][N] ;
int dx[8]={-1,-2,-2,-1,1,2,2,1},
    dy[8]={-2,-1,1,2,-2,-1,1,2};
bool check(int x,int y)
{
    return x>0&&y>0&&x<=n&&y<=n ;
}
int get(int x,int y)
{
    return (x-1)*n+y ;
}
int main()
{
    cin>>n>>m ;
    for(int i=1,x,y;i<=m;++i)
    {
        cin>>x>>y ;
        a[x][y]=1 ;
    }
    S=n*n+1 ; T=S+1 ;
    for(int i=1;i<=n;++i)
        for(int j=1;j<=n;j++) if((i+j)&1)
        {
            if(a[i][j]) continue ;
            add(S,get(i,j),1) ;
            for(int k=0;k<8;++k)
            {
                int x=i+dx[k],y=j+dy[k] ;
                if(check(x,y)&&!a[x][y]) add(get(i,j),get(x,y),1) ;
            }
        }
        else if(!a[i][j]) add(get(i,j),T,1) ;
    int flow,maxflow=0 ;
    while(bfs())
        while(flow=dinic(S,INF)) maxflow+=flow ;
    cout<<n*n-m-maxflow<<'\n' ;
    return 0 ;
}

C++(g++ 7.5.0) 解法, 执行用时: 211ms, 内存消耗: 5640K, 提交时间: 2023-01-03 15:24:59

// 最大独立集

#include<bits/stdc++.h>
using namespace std;
const int N = 40010, M = 500010, INF = 1e8;
int h[N], e[M], ne[M], f[M], idx, d[N], n, m, S, T, cur[M];

void add(int a, int b, int c)
{
    e[idx] = b, ne[idx] = h[a], f[idx] = c, h[a] = idx ++;
    e[idx] = a, ne[idx] = h[b], f[idx] = 0, h[b] = idx ++; 
}

bool bfs()
{
    queue<int>q;
    memset(d, -1, sizeof d);
    q.push(S);
    d[S] = 0;
    cur[S] = h[S];
    while(!q.empty())
    {
        auto t = q.front();
        q.pop();
        
        for(int i = h[t]; ~i; i = ne[i])
        {
            int j = e[i];
            if((d[j] == -1) && f[i])
            {
                d[j] = d[t] + 1;
                cur[j] = h[j];
                if(j == T) return true;
                q.push(j);
            }
        }
    }
    return false;
}

int find(int u, int limit)
{
    if(u == T) return limit;
    int flow = 0;
    for(int i = cur[u]; ~i && flow < limit; i = ne[i])
    {
        int j = e[i];
        cur[u] = i;
        if((d[j] == d[u] + 1) && f[i])
        {
            int t = find(j, min(f[i], limit - flow));
            if(!t) d[j] = -1;
            f[i] -= t, f[i ^ 1] += t, flow += t;
        }
    }
    return flow;
}

int dinic()
{
    int r = 0, flow;
    while(bfs()) while(flow = find(S, INF)) r += flow;
    return r;
}
int get(int x, int y)
{
	return (x - 1) * n + y;
}
char g[210][210];
int dx[] = {-2, -1, 1, 2, 2, 1, -1, -2}, dy[] = {1, 2, 2, 1, -1, -2, -2, -1};
int main()
{
    memset(h, -1, sizeof h);
	
	cin >> n >> m;

	S = 0, T = n * n + 1;	

	for(int i = 1; i <= m; i ++ )
	{
		int x, y;
		cin >> x >> y;
		g[x][y] = 'X';
	}
    int res = n * n - m;
	for(int i = 1; i <= n; i ++ )
		for(int j = 1; j <= n; j ++ )
			if((i + j & 1) && g[i][j] != 'X')
			{
				add(S, get(i, j), 1);
				for(int k = 0; k < 8; k ++ )
				{
					int a = i + dx[k], b = j + dy[k];
					if(a < 1 || b < 1 || a > n || b > n || g[a][b] == 'X') continue;
					add(get(i, j), get(a, b), INF);
				}
			}
			else if(g[i][j] != 'X')
				add(get(i, j), T, 1);
	cout << res - dinic() << '\n';
}

上一题