P3355 骑士共存问题
Posted garen-wang
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P3355 骑士共存问题相关的知识,希望对你有一定的参考价值。
二分图最大独立集
先给出二分图最大独立集的概念:选择最多的点,使任何边的两边不被同时选中。
并且有结论:最大独立集=节点总数-最大匹配。
这道题为什么是二分图?
我们可以通过((x,y))中的(x+y)的奇偶性来构造二分图,显然它们肯定不会互相攻击。
当一个点(x+y)为奇时,向它能攻击到的点都连一条权值为1的边。
这就是这个二分图的建图方法。
但是我不会匈牙利算法,直接网络流套下去就行了。
注意:那些障碍点对我们整个计算根本没有影响,直接忽略它们就可以了。节点总数也不用计算它们。
代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
const int maxn = 205, maxN = 40005;
const int INF = 0x3f3f3f3f;
const int dx[] = {-1, 1, -2, 2, -2, 2, -1, 1};
const int dy[] = {-2, -2, -1, -1, 1, 1, 2, 2};
struct Edges
{
int next, to, weight;
} e[4000005];
int head[maxN], tot = 1;
bool b[maxn][maxn];
int dep[maxN], cur[maxN];
int queue[maxN << 1], front, rear;
int n, m;
int s, t;
int cnt;
int id(int x, int y)
{
return (x - 1) * n + y;
}
void link(int u, int v, int w)
{
e[++tot] = (Edges){head[u], v, w};
head[u] = tot;
}
void addEdges(int u, int v, int w)
{
link(u, v, w);
link(v, u, 0);
}
bool bfs()
{
memset(dep, 0, sizeof dep);
front = rear = 0;
dep[s] = 1;
queue[rear++] = s;
while(front < rear)
{
int u = queue[front++];
for(int i = head[u]; i; i = e[i].next)
{
int v = e[i].to;
if(e[i].weight > 0 && !dep[v])
{
dep[v] = dep[u] + 1;
queue[rear++] = v;
}
}
}
return dep[t];
}
int dfs(int u, int flow)
{
if(u == t) return flow;
for(int &i = cur[u]; i; i = e[i].next)
{
int v = e[i].to;
if(e[i].weight > 0 && dep[v] == dep[u] + 1)
{
int di = dfs(v, std::min(flow, e[i].weight));
if(di > 0)
{
e[i].weight -= di;
e[i ^ 1].weight += di;
return di;
}
}
}
return 0;
}
int dinic()
{
int ans = 0;
while(bfs())
{
for(int i = 1; i <= t; i++) cur[i] = head[i];
while(int temp = dfs(s, INF)) ans += temp;
}
return ans;
}
int main()
{
scanf("%d", &n);
for(int i = 1; i <= n; i++)
{
for(int j = 1; j <= n; j++)
{
int temp; scanf("%1d", &temp);
b[i][j] = temp;
if(temp) cnt++;
}
}
s = n * n + 1, t = s + 1;
for(int i = 1; i <= n; i++)
{
for(int j = 1; j <= n; j++)
{
if(b[i][j]) continue;
if((i + j) % 2)
{
addEdges(s, id(i, j), 1);
for(int k = 0; k < 8; k++)
{
int nx = i + dx[k], ny = j + dy[k];
if(nx >= 1 && nx <= n && ny >= 1 && ny <= n)
{
addEdges(id(i, j), id(nx, ny), 1);
}
}
}
else
{
addEdges(id(i, j), t, 1);
}
}
}
printf("%d
", n * n - cnt - dinic());
return 0;
}
以上是关于P3355 骑士共存问题的主要内容,如果未能解决你的问题,请参考以下文章