• CodeForces


    题意

    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;
    }
    

      

  • 相关阅读:
    apache 问题 You don't have permission to access /test.php on this server 解决方法
    setTimeout和setInterval实现定时器的区别
    视图Ext.Viewport和窗口Ext.Window用法
    JavaScript设置Cookie
    布局Layout
    html中select标签刷新后不回到默认值而是保持之前选择值
    设置session失效的几种方法
    面板Ext.Panel使用
    树TreePanel
    让html元素随浏览器的大小自适应垂直居中
  • 原文地址:https://www.cnblogs.com/mcq1999/p/11838405.html
Copyright © 2020-2023  润新知