D. Paint the Tree

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;
}
posted @ 2019-10-14 22:28  moxin0509  阅读(319)  评论(0编辑  收藏  举报