题意:一棵n个节点的树,给每个节点上色,有三种颜色可以选择。但每个节点,涂不同颜色的代价是不同的。上色后,满足任意一个(x,y,z)x,y之间有边,y,z之间有边;且x,y,z三点的颜色不同。问最小代价。
思路:显然这是一个树的染色问题,那么其实根据题意,我们分析一容易发现当一个点度大于2那么肯定是无解的,有解的情况必然是一条链,那么我们只要建图找到度为1的点,跑6种情况的染色方案即可
//最小值开小了 困了我2个小时。。
#include<bits/stdc++.h>
#define ll long long
#define N 0x3f3f3f3f3f3f3f3f
using namespace std;
const int maxn=1e5+10;
int cnt;
int cc[10][maxn];
vector<int>vt[100010];
struct node
{
ll x,y,z;
int depth;
int f;
} r[maxn];
struct nod
{
ll x,y,z;
} d[10];
int cmp(node xx,node yy)
{
return xx.depth<yy.depth;
}
map<int,int>mp;
map<int,int>mpp;
void dfs(int x,int ct,int per)
{
r[x].depth=ct;
mp[ct]=x;
for(int i=0; i<vt[x].size(); i++)
{
if(vt[x][i]!=per)
dfs(vt[x][i],ct+1,x);
}
}
int da,db,dc;
ll minn=1e18;
int n;
void dfs1(int a,int b,int c)
{
d[1].x=a,d[1].y=b,d[1].z=c;
ll sum=0;
for(int i=1; i<=n; i++)
{
if(i%3==0)
{
sum+=cc[d[1].z][mp[i]];
}
if(i%3==1)
{
sum+=cc[d[1].x][mp[i]];
}
if(i%3==2)
{
sum+=cc[d[1].y][mp[i]];
}
}
if(sum<minn)
{
minn=sum;
da=a,db=b,dc=c;
}
}
int main()
{
cnt=1;
cin>>n;
for(int i=1; i<=3; i++)
{
for(int j=1; j<=n; j++)
cin>>cc[i][j];
}
for(int i=1; i<=n-1; i++)
{
int u,v;
cin>>u>>v;
vt[v].push_back(u);
vt[u].push_back(v);
}
int flag=0;
for(int i=1; i<=n; i++)
{
if(vt[i].size()==1)
{
if(flag==0)
flag=i;
}
if(vt[i].size()>2)
{
cout<<-1<<endl;
return 0;
}
}
dfs(flag,cnt,0);
sort(r+1,r+n+1,cmp);
dfs1(1,2,3);
dfs1(1,3,2);
dfs1(2,1,3);
dfs1(2,3,1);
dfs1(3,2,1);
dfs1(3,1,2);
cout<<minn<<endl;
for(int i=1; i<=n; i++)
{
if(i%3==0)
{
mpp[mp[i]]=dc;
}
if(i%3==1)
{
mpp[mp[i]]=da;
}
if(i%3==2)
{
mpp[mp[i]]=db;
}
}
for(int i=1; i<=n; i++)
{
cout<<mpp[i]<<" ";
}
cout<<endl;
return 0;
}