Paint the Tree CodeForces - 1244D 暴力+邻接表

问题:

You are given a tree consisting of n vertices. A tree is an undirected connected acyclic graph.

                                      Example of a tree.
You have to paint each vertex into one of three colors. For each vertex, you know the cost of painting it in every color.

You have to paint the vertices so that any path consisting of exactly three distinct vertices does not contain any vertices with equal colors. In other words, let's consider all triples (x,y,z) such that x≠y,y≠z,x≠z, x is connected by an edge with y, and y is connected by an edge with z. The colours of x, y and z should be pairwise distinct. Let's call a painting which meets this condition good.

You have to calculate the minimum cost of a good painting and find one of the optimal paintings. If there is no good painting, report about it.

 

Input


The first line contains one integer n (3≤n≤100000) — the number of vertices.

The second line contains a sequence of integers c1,1,c1,2,…,c1,n (1≤c1,i≤109), where c1,i is the cost of painting the i-th vertex into the first color.

The third line contains a sequence of integers c2,1,c2,2,…,c2,n (1≤c2,i≤109), where c2,i is the cost of painting the i-th vertex into the second color.

The fourth line contains a sequence of integers c3,1,c3,2,…,c3,n (1≤c3,i≤109), where c3,i is the cost of painting the i-th vertex into the third color.

Then (n−1) lines follow, each containing two integers uj and vj (1≤uj,vj≤n,uj≠vj) — the numbers of vertices connected by the j-th undirected edge. It is guaranteed that these edges denote a tree.

Output


If there is no good painting, print −1.

Otherwise, print the minimum cost of a good painting in the first line. In the second line print n integers b1,b2,…,bn (1≤bi≤3), where the i-th integer should denote the color of the i-th vertex. If there are multiple good paintings with minimum cost, print any of them.

Examples


Input
3
3 2 3
4 3 2
3 1 3
1 2
2 3
Output
6
1 3 2 


Input
5
3 4 2 1 2
4 2 1 5 4
5 3 2 1 1
1 2
3 2
4 3
5 3
Output
-1


Input
5
3 4 2 1 2
4 2 1 5 4
5 3 2 1 1
1 2
3 2
4 3
5 4
Output
9
1 3 2 1 3 


Note
All vertices should be painted in different colors in the first example. The optimal way to do it is to paint the first vertex into color 1, the second vertex — into color 3, and the third vertex — into color 2. The cost of this painting is 3+2+1=6.

问题:给一个数n表示n个点,下面有三行,第一行表示n个点对应第一种颜色的价钱,第二行表示n个点对应第二种颜色的价钱,第三行表示n个点对应第三种颜色的价钱,共有三种颜色,接下来是n-1条边,三个不同顶点组成的任何路径都不包含任何具有相同颜色的顶点,意思是只能为一条链,求把所有点涂上颜色最小花费。

思路:由于只是一个链状,所有只需要确定开头的前两个就可以确定整条链(因为只有三种颜色),开头前两个共有6种情况,暴力便利6遍即可。

代码:
 

#include<stdio.h>
#include<string.h>
#include<algorithm>
#define N 200100
using namespace std;
typedef long long ll;
ll s[200010][4],sum;
ll r[7];
int q[7][2*N];
ll nex[2*N],first[2*N],w[2*N],du[2*N];
bool tag[2*N];
ll dfs(int x,int y,ll z,int v)
{
    memset(tag,0,sizeof(tag));
    tag[z]=1;
    int book[4]= {0};
    book[x]=1;
    book[y]=1;
    sum=0;
    sum+=s[z][x];
    q[v][z]=x;
    ll jj=first[z];
    ll tt=w[jj];
    tag[tt]=1;
    sum+=s[tt][y];
    q[v][tt]=y;
    for(int j=first[tt]; j!=-1;)
    {
        int h=w[j],flag1=0;
        if(book[6-x-y]==0&&tag[h]==0)
        {
            flag1=1;
            tag[h]=1;
            sum+=s[h][6-x-y];
            book[6-x-y]=1;
            book[x]=0;
            q[v][h]=6-x-y;
        }
        else if(book[x]==0&&tag[h]==0)
        {
            flag1=1;
            tag[h]=1;
            sum+=s[h][x];
            book[x]=1;
            book[y]=0;
            q[v][h]=x;
        }
        else if(book[y]==0&&tag[h]==0)
        {
            flag1=1;
            tag[h]=1;
            sum+=s[h][y];
            book[y]=1;
            book[6-x-y]=0;
            q[v][h]=y;
        }
        if(flag1==0)
            j=nex[j];
        else
            j=first[h];
    }
    return sum;
}
int main()
{
    ll n;
    scanf("%lld",&n);
    for(int j=1; j<=3; j++)
        for(int i=1; i<=n; i++)
            scanf("%lld",&s[i][j]);
    ll a,b,t=1;
    memset(du,0,sizeof(du));
    memset(first,-1,sizeof(first));
    for(ll i=1; i<n; i++)
    {
        scanf("%lld%lld",&a,&b);
        du[a]++;
        du[b]++;
        w[t]=b;
        nex[t]=first[a];
        first[a]=t++;
        nex[t]=first[b];
        w[t]=a;
        first[b]=t++;
    }
    int flag=0,kk;
    for(int i=1; i<=n; i++)
    {
        if(du[i]>2)
        {
            flag=1;
            break;
        }
        if(du[i]==1)
            kk=i;
    }
    if(flag==1)
    {
        printf("-1\n");
        return 0;
    }
    ll maxx=1e18;
    r[1]=dfs(1,2,kk,1);
    r[2]=dfs(2,1,kk,2);
    r[3]=dfs(1,3,kk,3);
    r[4]=dfs(3,1,kk,4);
    r[5]=dfs(3,2,kk,5);
    r[6]=dfs(2,3,kk,6);
    int f;
    for(int i=1; i<=6; i++)
    {
        if(maxx>r[i])
        {
            maxx=r[i];
            f=i;
        }
    }
    printf("%lld\n",maxx);
    for(int i=1; i<=n; i++)
        if(i==1)
            printf("%d",q[f][i]);
        else
            printf(" %d",q[f][i]);
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值