D. Paint the Tree
[思路]:显然这是一个树的染色问题,那么其实根据题意,我们分析一容易发现当一个点度大于2那么肯定是无解的,有解的情况必然是一条链,那么我们只要建图找到度为1的点,跑6种情况的染色方案即可
原题链接
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
const int MAXN = 100005;
typedef long long LL;
int head[MAXN], vids[MAXN], du[MAXN];
int tot;
void Init(){
tot = 0;
memset(head, -1, sizeof(head));
}
struct NODE{
int u, v, next;
}edge[MAXN << 2];
void add(int u, int v){
edge[tot].u = u, edge[tot].v = v, edge[tot].next = head[u], head[u] = tot ++;
}
LL arr[MAXN], brr[MAXN], crr[MAXN];
LL PD(int num, int i){
//cout << arr[i] << " " << brr[i] << " " << crr[i] << endl;
if(num == 0) return arr[i];
if(num == 1) return brr[i];
if(num == 2) return crr[i];
}
LL judge(int begin, int x, int y, int z){
memset(vids, 0, sizeof(vids));
int num = 0;
vids[begin] = 1;
LL re = 0;
if(num % 3 == 0) re += PD(x, begin);
if(num % 3 == 1) re += PD(y, begin);
if(num % 3 == 2) re += PD(z, begin);
num ++;
queue<int>que;
while(!que.empty()){
que.pop();
}
que.push(begin);
while(!que.empty()){
int xx = que.front();
que.pop();
for(int i = head[xx]; ~i; i = edge[i].next){
if(!vids[edge[i].v]){
que.push(edge[i].v);
vids[edge[i].v] = 1;
if(num % 3 == 0) re += PD(x, edge[i].v);
if(num % 3 == 1) re += PD(y, edge[i].v);
if(num % 3 == 2) re += PD(z, edge[i].v);
//cout << re << " " << edge[i].v << " " << PD(x, edge[i].v) << " " << PD(y, edge[i].v) << " " << PD(y, edge[i].v) << endl;
num ++;
}
}
}
return re;
}
void Print(int num, int n, int x, int y, int z){
memset(vids, 0, sizeof(vids));
int result[MAXN];
for(int i = 0; i <= n; i ++) result[i] = 0;
queue<int>que;
while(!que.empty()){
que.pop();
}
que.push(num);
vids[num] = 1;
int flag = 0;
if(flag % 3 == 0) result[num] = x;
if(flag % 3 == 1) result[num] = y;
if(flag % 3 == 2) result[num] = z;
flag ++;
while(!que.empty()){
int xx = que.front();
que.pop();
for(int i = head[xx]; ~i; i = edge[i].next){
if(!vids[edge[i].v]){
que.push(edge[i].v);
vids[edge[i].v] = 1;
if(flag % 3 == 0) result[edge[i].v] = x;
if(flag % 3 == 1) result[edge[i].v] = y;
if(flag % 3 == 2) result[edge[i].v] = z;
flag ++;
}
}
}
for(int i = 1; i <= n; i ++){
cout << result[i] + 1 << " ";
}
cout << endl;
}
int main(){
int n;
ios::sync_with_stdio(false);
cin >> n;
for(int i = 1; i <= n; i ++) cin >> arr[i];
for(int i = 1; i <= n; i ++) cin >> brr[i];
for(int i = 1; i <= n; i ++) cin >> crr[i];
Init();
for(int i = 1; i < n; i ++){
int u, v;
cin >> u >> v;
add(u, v), add(v, u);
du[u] ++, du[v] ++;
}
for(int i = 1; i <= n; i ++){
if(du[i] > 2){
cout << "-1\n";
return 0;
}
}
int num;
for(int i = 1; i <= n; i ++) if(du[i] == 1) {num = i; break;}
long long re1 = judge(num, 0, 1, 2);
long long re2 = judge(num, 0, 2, 1);
long long re3 = judge(num, 1, 0, 2);
long long re4 = judge(num, 1, 2, 0);
long long re5 = judge(num, 2, 1, 0);
long long re6 = judge(num, 2, 0, 1);
//cout << re1 << " " << re2 << " " << re3 << " " << re4 << " " << re5 << " " << re6 << endl;
int nums = 1;
if(re1 > re2){
re1 = re2;
nums = 2;
}
if(re1 > re3){
re1 = re3;
nums = 3;
}
if(re1 > re4){
re1 = re4;
nums = 4;
}
if(re1 > re5){
re1 = re5;
nums = 5;
}
if(re1 > re6){
re1 = re6;
nums = 6;
}
cout << re1 << endl;
if(nums == 1){
Print(num, n, 0, 1, 2);
}
if(nums == 2){
Print(num, n, 0, 2, 1);
}
if(nums == 3){
Print(num, n, 1, 0, 2);
}
if(nums == 4){
Print(num, n, 1, 2, 0);
}
if(nums == 5){
Print(num, n, 2, 1, 0);
}
if(nums == 6){
Print(num, n, 2, 0, 1);
}
return 0;
}