解题报告:CF1244D
题目链接;CF1244D Paint the Tree
暴毙。
手玩一下,就会发现只有树是链的情况下才有解,就可以搞到序列上做运算了。
然后莽了一发\(dp\),然后就炸了,原因是一个点的颜色受前两个点控制,而不是只有上一个。
其实确定序列后只有\(3!=6\)中选法,由于第三个是前两个控制的,且是唯一的,然后就行了。
最后把每个点和编号对应起来就好了。
效率是\(\mathcal O(n)\)的,可以通过本题。
下面是我睿智的代码与正解的集合:
\(Code\):
#include<iostream>
#include<cstdio>
using namespace std;
#define ll long long
#define MAXN 100005
#define INF 1ll<<61
int deg[MAXN];
struct node
{
int to,nxt;
}e[MAXN<<1];
int head[MAXN],cnt=0;
void add(int l,int r)
{
e[++cnt].to=r;
e[cnt].nxt=head[l];
head[l]=cnt;
}
ll f[5][MAXN],a[5][MAXN],sum,maxn;
int id[MAXN],ans[MAXN];
int c=0;
void dfs(int cur,int fa)
{
f[0][++c]=a[0][cur];
f[1][c]=a[1][cur];
f[2][c]=a[2][cur];
id[c]=cur;
for(int i=head[cur];i;i=e[i].nxt) if(fa!=e[i].to) dfs(e[i].to,cur);
}
int n,u,v;
int rt[MAXN],rl;
//我是真的菜
int main()
{
#define read(x) scanf("%d",&x)
#define read_l(x) scanf("%lld",&x)
read(n);
for(int i=1;i<=n;i++) read_l(a[0][i]);
for(int i=1;i<=n;i++) read_l(a[1][i]);
for(int i=1;i<=n;i++) read_l(a[2][i]);
for(int i=1;i<n;i++)
{
read(u),read(v);
add(u,v),add(v,u);
deg[u]++,deg[v]++;
if(deg[u]>=3||deg[v]>=3)
{
printf("%d\n",-1);
return 0;
}
}
for(int i=1;i<=n;i++) if(deg[i]==1){dfs(i,i);break;}
/*for(int i=1;i<=n;i++)
{
dp[0][i]=dp[1][i]=dp[2][i]=INF;
for(int j=0;j<=2;j++)
{
for(int k=0;k<=2;k++)
{
if(j==k) continue;
if(dp[k][i-1]+f[j][i]<dp[j][i]) dp[j][i]=dp[k][i-1]+f[j][i],t[j][i]=k;
}
}
}*/
int op=0;
maxn=INF;
for(int i=1;i<=3;i++)
{
for(int j=1;j<=3;j++)
{
if(i==j) continue;
op++;
rt[1]=i,rt[2]=j,sum=f[i-1][1]+f[j-1][2];
for(int k=3;k<=n;k++) rt[k]=6-rt[k-1]-rt[k-2],sum+=f[rt[k]-1][k];
if(sum<maxn) maxn=sum,rl=op;
}
}
printf("%lld\n",maxn);
int co=0;
for(int i=1;i<=3;i++)
{
for(int j=1;j<=3;j++)
{
if(i==j) continue;
co++;
if(co==rl)
{
ans[id[1]]=i,ans[id[2]]=j,rt[1]=i,rt[2]=j,sum=f[i-1][1]+f[j-1][2];
for(int k=3;k<=n;k++) ans[id[k]]=6-rt[k-1]-rt[k-2],rt[k]=ans[id[k]],sum+=f[rt[k]-1][k];
break;
}
}
}
/*if(dp[0][n]<dp[1][n]&&dp[0][n]<dp[2][n])
{
printf("%lld\n",dp[0][n]);
ans[id[n]]=1;
int k=0;
for(int i=n;i>=2;i--) ans[id[i-1]]=t[k][i]+1,k=t[k][i];
}
else if(dp[1][n]<dp[0][n]&&dp[1][n]<dp[2][n])
{
printf("%lld\n",dp[1][n]);
ans[id[n]]=2;
int k=1;
for(int i=n;i>=2;i--) ans[id[i-1]]=t[k][i]+1,k=t[k][i];
}
else
{
printf("%lld\n",dp[2][n]);
ans[id[n]]=3;
int k=2;
for(int i=n;i>=2;i--) ans[id[i-1]]=t[k][i]+1,k=t[k][i];
}*/
for(int i=1;i<=n;i++) printf("%d ",ans[i]);
return 0;
}