【LOJ3279】「JOISC 2020 Day3」迷路的貓

題目鏈接

點擊打開鏈接

題目解法

對於 A3A\geq 3 的情況,考慮從 00 號點出發,求出到各個點的最短路 distidist_i
則對於一條邊 (x,y)(x,y)distxdisty1|dist_x-dist_y|\leq 1 ,將其染色爲 min{distx,disty}%3min\{dist_x,dist_y\}\%3
對於任意一個點 xx ,與其相鄰的邊權值應當至多有兩種,找出表示 distdist 減一的那一種即可。

時間複雜度 O(N+M)O(N+M) ,沒有多餘步數。

對於 A=2A=2 的情況,首先考慮樹是一條鏈的情況。
考慮對邊進行 001101001101 爲一個循環節的染色,則無論身處何處,向一個方向走 33 步即可唯一確定自己的位置和方向,從而在多餘步數不超過 66 的情況下達成目標。

對於樹不是一條鏈的情況,考慮將度數 3\geq 3 的點的父邊與子樹邊染上不同的顏色。那麼,一旦經過度數 3\geq 3 的點,方向便能確定,從而我們只需要在樹上的每一條鏈重複鏈上的算法即可。

時間複雜度 O(N)O(N) ,多餘步數不超過 66

#include "stray.h"
#include<bits/stdc++.h>
using namespace std;
namespace Anthony {
	const int MAXN = 2e4 + 5;
	const int value[6] = {0, 0, 1, 1, 0, 1};
	vector <int> res; int n, m;
	vector <pair <int, int>> a[MAXN];
	void dfs(int pos, int fa) {
		if (fa == -1) {
			for (auto x : a[pos]) {
				res[x.second] = 0;
				dfs(x.first, x.second);
			}
		} else if (a[pos].size() <= 2) {
			int ans = (res[fa] + 1) % 6;
			for (auto x : a[pos])
				if (x.second != fa) {
					res[x.second] = ans;
					dfs(x.first, x.second);
				}
		} else {
			int ans = (value[res[fa]] == 0) ? 2 : 0;
			for (auto x : a[pos])
				if (x.second != fa) {
					res[x.second] = ans;
					dfs(x.first, x.second);
				}
		}
	}
}
vector <int> Mark(int N, int M, int A, int B, vector <int> u, vector <int> v) {
	using namespace Anthony;
	n = N, m = M, res.resize(m);
	for (int i = 0; i <= m - 1; i++) {
		int x = u[i], y = v[i];
		a[x].emplace_back(y, i);
		a[y].emplace_back(x, i);
	}
	if (A > 2) {
		static int q[MAXN], dist[MAXN];
		int l = 0, r = 0; dist[0] = 1, q[l = r = 0] = 0;
		while (l <= r) {
			int pos = q[l++];
			for (auto x : a[pos])
				if (dist[x.first] == 0) {
					dist[x.first] = dist[pos] + 1;
					q[++r] = x.first;
				}
		}
		for (int i = 0; i <= m - 1; i++)
			res[i] = min(dist[u[i]], dist[v[i]]) % 3;
		return res;
	}
	dfs(0, -1);
	for (int i = 0; i <= m - 1; i++)
		res[i] = value[res[i]];
	return res;
}
namespace Catherine {
	const int MAXN = 2e4 + 5;
	const int v[6] = {1, 0, 1, 1, 0, 0};
	bool sure, type;
	int r; vector <int> a[5];
	int cur, last, edge[5];
}
void Init(int A, int B) {
	using namespace Catherine;
	sure = false, type = A == 2, r = 0, last = -1;
}
int Move(vector <int> y) {
	using namespace Catherine;
	if (!type) {
		if (last != -1) y[last]++;
		for (int i = 0; i <= 2; i++)
			if (y[i] && !y[(i + 2) % 3]) {
				last = i;
				break;
			}
		return last;
	}
	if (last == -1) {
		assert(!sure);
		if (y[0] + y[1] >= 3 || y[0] + y[1] <= 1) {
			sure = true;
			if (y[0] == 1) last = 0;
			else last = 1;
		} else {
			a[++r] = y;
			if (y[0] != 0) last = 0;
			else last = 1;
			edge[r] = last;
		}
	} else {
		if (sure) {
			if (y[0] + y[1] == 1) {
				if (y[0] != 0) last = 0;
				else last = 1;
			} else {
				y[last]++;
				if (y[0] == 1) last = 0;
				else last = 1;
			}
		} else if (y[0] + y[1] != 1) {
			sure = true;
			if (y[0] + y[1] == 0) return -1;
			if (y[last] != 0) last ^= 1;
			else return -1;
		} else if (r < 3) {
			int nxt = 0;
			if (y[0] != 0) nxt = 0;
			else nxt = 1;
			y[last]++, last = nxt;
			a[++r] = y;
			edge[r] = last;
		} else {
			bool ans = false;
			y[last]++, a[4] = y;
			for (int i = 0; i <= 5; i++) {
				bool res = true;
				for (int j = 1; j <= 3; j++)
					res &= edge[j] == v[(i + j) % 6];
				for (int j = 1; j <= 4; j++) {
					vector <int> tmp(2);
					tmp[v[(i + j) % 6]]++;
					tmp[v[(i + j - 1) % 6]]++;
					res &= a[j] == tmp;
				}
				if (res) ans = true;
			}
			sure = true;
			if (ans) {
				y[last]--;
				if (y[0] != 0) last = 0;
				else last = 1;
			} else return -1;
		}
	}
	return last;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章