zoj3316.Game【带花树】

100 阅读1分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

传送门 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;
}