Codeforces Round #592 (Div. 2) D题

Paint the Tree

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

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.

题目大意为:给你一颗树,给树的结点涂颜色,树的所有相邻的三个结点都必须都是不同的颜色;每个结点涂不同的颜色的花费都不一样;要求最小花费;然后输出每个结点的颜色,是依次1-n每个结点不是树的结点顺序

1.显然,如果树有分叉那么肯定不行;
2.那么树就是一条直链,因为只有三种颜色,所以只要控制前面两个结点颜色,整条链的颜色就决定了;所有枚举前面两种颜色,6种情况;

代码:

#include<bits/stdc++.h>
#define LL long long
#define pa pair<int,int>
#define lson k<<1
#define rson k<<1|1
#define N 500100
#define M 2000010
using namespace std;
int a[4][100100];
int n;
struct Node{
	int to,next;
}edge[200100];
int vis[100100];//某个点的度数 
int head[100100];
int cnt;
void add(int p,int q){
	edge[cnt].to=q;
	edge[cnt].next=head[p];
	head[p]=cnt++;
}
int st;
bool v[100100];
int len[100100];//路径 
void dfs(int p,int step){//确定路径 
	len[step]=p;
	v[p]=true;
	for(int i=head[p];~i;i=edge[i].next){
		if(v[edge[i].to]) continue;
		step++;
		dfs(edge[i].to,step);
	}
}
int step[100100];
LL sum;
LL mmin=1e18;
int f[100100];
int main(){
	memset(head,-1,sizeof(head));
	scanf("%d",&n);
	for(int i=1;i<=3;i++){
		for(int j=1;j<=n;j++) scanf("%d",&a[i][j]);
	} 
	int p,q;
	for(int i=1;i<=n-1;i++){
		scanf("%d%d",&p,&q);
		add(p,q);
		add(q,p);
	}
	for(int i=1;i<=n;i++){
		for(int j=head[i];~j;j=edge[j].next){
			vis[edge[j].to]++;
		}
	}
	for(int i=1;i<=n;i++){
		if(vis[i]>=3){//度数大于3说明有分支链,直接结束 
			cout<<"-1"<<endl;
			return 0;
		}
		if(vis[i]==1){//首节点 
			if(st==0) st=i;
		}
	}
	dfs(st,1);//确定路径 
	int ans;
	int a1,a2;
	for(int i=1;i<=3;i++){//第一个点
		for(int j=1;j<=3;j++){//第二个点 
			ans=0;
			sum=0;
			if(i==j) continue;
			step[++ans]=i;
			sum=sum+(LL)a[i][len[ans]];
			step[++ans]=j;
			sum=sum+(LL)a[j][len[ans]];
			for(int k=3;k<=n;k++){
				for(int l=1;l<=3;l++){//第三个点 
					if(l==step[k-1]||l==step[k-2]) continue;
					step[++ans]=l;
					sum=sum+(LL)a[l][len[ans]];
					
				}
			}
			if(mmin>sum){
				mmin=sum;
				a1=i,a2=j;
			} 
		}
	}
	cout<<mmin<<endl;
	ans=0;
	step[++ans]=a1;
	f[len[ans]]=a1;
	step[++ans]=a2;
	f[len[ans]]=a2;
	for(int i=3;i<=n;i++){
		for(int j=1;j<=3;j++){
			if(j==step[i-1]||j==step[i-2]) continue;
			step[++ans]=j;
			f[len[ans]]=j;
		}
	}
	for(int i=1;i<=n;i++) printf("%d ",f[i]);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值