CodeForces - 1244D (思维+暴力)

题意

https://vjudge.net/problem/CodeForces-1244D

有一棵树,有3种颜色,第i个节点染成第j种颜色的代价是c(i,j),现在要你求出一种染色方案,使得总代价最小,且对于任意三个相邻的节点,颜色不能相同。输出最小代价与其中一种方案。无解输出-1

思路

首先可以发现当一个点的度数为3,那么它连的三个点的颜色必须互不相同,这样就把三种三色用完了,这个点就染不了了,于是如果存在度大于等于3的点,那么无解。

那么有解的树可以伸直成一条链,我们暴力枚举任意相邻的三个点的颜色,有3!种,然后我们暴力dfs从这三点的两端向外延伸即可。

复杂度O(6*n)

代码

#include<bits/stdc++.h>
using namespace std;
#define inf 0x3f3f3f3f
#define ll long long
const int N=1e5+5;
const int mod=1e9+7;
const double eps=1e-8;
const double PI = acos(-1.0);
#define lowbit(x) (x&(-x))
ll c[4][N];
ll du[N],col[N],rec[N];
vector<int>g[N];
int flag=0,s,a,b;
void dfs(int u,int fa)
{
    int sz=g[u].size();
    for(int i=0; i<sz; i++)
    {
        int v=g[u][i];
        if(v==fa)
            continue;
        for(int i=1; i<=3; i++)
        {
            if(col[fa]!=i&&col[u]!=i)
            {
                col[v]=i;
                break;
            }
        }
        dfs(v,u);
    }
}
int main()
{
    std::ios::sync_with_stdio(false);
    int n;
    cin>>n;
    for(int i=1; i<=3; i++)
    {
        for(int j=1; j<=n; j++)
        {
            cin>>c[i][j];
        }
    }
    for(int i=0; i<n-1; i++)
    {
        int u,v;
        cin>>u>>v;
        g[u].push_back(v);
        g[v].push_back(u);
        du[u]++,du[v]++;
        if(du[u]==2)
        {
            s=u;
        }
        if(du[v]==2)
            s=v;
        if(du[u]>=3||du[v]>=3)
        {
            flag=1;
        }
    }

    if(flag)
    {
        cout<<-1<<endl;
        return 0;
    }
    a=g[s][0],b=g[s][1];
    ll ans=1e16;
    for(int i=1; i<=3; i++)
    {
        for(int j=1; j<=3; j++)
        {
            for(int k=1; k<=3; k++)
            {
                if(i==j||j==k||i==k) continue;
                for(int i=1; i<=n; i++)
                    col[i]=0;
                col[s]=i,col[a]=j,col[b]=k;
                dfs(a,s);
                dfs(b,s);
                ll sum=0;
                for(int i=1; i<=n; i++)
                {
                    sum+=c[col[i]][i];
                }
                if(sum<ans)
                {
                    ans=sum;
                    for(int i=1; i<=n; i++)
                        rec[i]=col[i];
                }
            }
        }
    }
    cout<<ans<<endl;
    for(int i=1; i<=n; i++)
        cout<<rec[i]<<" ";
    cout<<endl;
    return 0;
}

  

posted @ 2019-11-11 20:56  MCQ1999  阅读(203)  评论(0编辑  收藏  举报