題目鏈接
題目解法
對於 的情況,考慮從 號點出發,求出到各個點的最短路 。
則對於一條邊 , ,將其染色爲 。
對於任意一個點 ,與其相鄰的邊權值應當至多有兩種,找出表示 減一的那一種即可。
時間複雜度 ,沒有多餘步數。
對於 的情況,首先考慮樹是一條鏈的情況。
考慮對邊進行 爲一個循環節的染色,則無論身處何處,向一個方向走 步即可唯一確定自己的位置和方向,從而在多餘步數不超過 的情況下達成目標。
對於樹不是一條鏈的情況,考慮將度數 的點的父邊與子樹邊染上不同的顏色。那麼,一旦經過度數 的點,方向便能確定,從而我們只需要在樹上的每一條鏈重複鏈上的算法即可。
時間複雜度 ,多餘步數不超過 。
#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;
}