本文已参与「新人创作礼」活动,一起开启掘金创作之路。
传送门 zoj3316 给定一个棋盘,棋盘上有些点 轮流移除,距离上次移除的棋子的哈密顿距离,不大于K的棋子 第一步移除任选棋子,问是否后手必胜?
分析
第一步任选,所以直接看最大匹配是多少 将距离不大于K的点都连起来 跑一般图最大匹配
如果匹配的点数量刚好等于所有点的数量,说明整个图就形成一个完美匹配 只要先手拿走一个棋子,后手拿与这个棋子匹配的棋子即可,后手一定有解,也就是先手必败,后手必胜
代码
//zoj316
/*
@Author: YooQ
*/
#include <bits/stdc++.h>
using namespace std;
#define sc scanf
#define pr printf
#define ll long long
#define int long long
#define FILE_OUT freopen("out", "w", stdout);
#define FILE_IN freopen("in", "r", stdin);
#define debug(x) cout << #x << ": " << x << "\n";
#define AC 0
#define WA 1
#define INF 0x3f3f3f3f
const ll MAX_N = 1e6+5;
const ll MOD = 1e9+7;
int N, M, K;
int head[MAX_N];
int tot = 0;
struct Edge {
int to, nxt;
}edge[MAX_N];
void addEdge(int u, int v) {
edge[tot].nxt = head[u];
edge[tot].to = v;
head[u] = tot++;
edge[tot].nxt = head[v];
edge[tot].to = u;
head[v] = tot++;
}
int father[MAX_N];
int match[MAX_N];
int vis[MAX_N];
int pre[MAX_N];
int tim = 0;
int dfn[MAX_N];
queue<int>Q;
int find(int x) {
return x == father[x] ? x : father[x] = find(father[x]);
}
int LCA(int x, int y) {
++tim;
x = find(x);
y = find(y);
while (dfn[x] != tim) {
dfn[x] = tim;
x = find(pre[match[x]]);
if (y) swap(x, y);
}
return x;
}
void fix(int x) {
int nxt = 0;
while (x) {
nxt = match[pre[x]];
match[x] = pre[x];
match[pre[x]] = x;
x = nxt;
}
}
void blossom(int x, int y, int lca) {
while (find(x) != lca) {
pre[x] = y;
y = match[x];
if (vis[y] == 2) vis[y] = 1, Q.push(y);
if (find(x) == x) father[x] = lca;
if (find(y) == y) father[y] = lca;
x = pre[y];
}
}
bool aug(int u) {
while (Q.size()) Q.pop();
for (int i = 1; i <= N; ++i) {
father[i] = i;
pre[i] = vis[i] = 0;
}
Q.push(u);
vis[u] = 1;
int v;
while (Q.size()) {
u = Q.front();Q.pop();
for (int i = head[u];~i;i=edge[i].nxt) {
if (vis[v=edge[i].to] == 2 || find(u) == find(v)) continue;
if (!vis[v]) {
vis[v] = 2;
pre[v] = u;
if (!match[v]) {
fix(v);
return true;
}
vis[match[v]] = 1;
Q.push(match[v]);
} else {
int lca = LCA(u, v);
blossom(u, v, lca);
blossom(v, u, lca);
}
}
}
return false;
}
struct Node {
int x, y;
int operator + (const Node& B) const {
return abs(x - B.x) + abs(y - B.y);
}
}arr[MAX_N];
void init() {
memset(head, -1, sizeof head);
memset(match, 0, sizeof match);
tot = 0;
}
void solve(){
init();
for (int i = 1; i <= N; ++i) {
cin >> arr[i].x >> arr[i].y;
}
cin >> K;
for (int i = 1; i <= N; ++i) {
for (int j = i+1; j <= N; ++j) {
if (arr[i] + arr[j] <= K) {
addEdge(i, j);
}
}
}
int ans = 0;
for (int i = 1; i <= N; ++i) {
if (!match[i]) ans += aug(i);
}
ans *= 2;
if (ans == N) {
puts("YES");
} else {
puts("NO");
}
}
signed main()
{
#ifndef ONLINE_JUDGE
FILE_IN
FILE_OUT
#endif
int T = 1;//cin >> T;
while (~sc("%lld", &N)) solve();
return AC;
}