codeforces1244——D.Paint the Tree(dfs)

原题链接
题意:
给定一棵树,每个节点都可以涂三种颜色,分别有不同的代价。现在要求你对一棵树进行涂色,要求任意相邻的三个点的颜色都不同,求最小代价和任意一种涂色方案,没有方案输出-1
思路:
首先,如果一个节点的度数大于3那就必然不能成功涂色。
假设A的出度点是B,C,D.那么无论怎么组合,都无法使得任意三个点的颜色相同。
所以这棵树只有由度数为1和2的点构成的时候才可以被涂色,这时候就相当于一条链。
从链的一端开始涂色,当前两个点的颜色确定时,第三个点的颜色也会确定,相继会确定所有点的颜色。我们只需要枚举前两个点的涂色方案,从而计算出每一种涂色方案的权值,记录最小值即可。
代码:

#pragma GCC optimize(3)
#pragma GCC optimize("Ofast","unroll-loops","omit-frame-pointer","inline")
#pragma GCC optimize(2)
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<ll,ll>PLL;
typedef pair<int,int>PII;
typedef pair<double,double>PDD;
#define I_int ll
inline ll read()
{
    ll x=0,f=1;
    char ch=getchar();
    while(ch<'0'||ch>'9')
    {
        if(ch=='-')f=-1;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9')
    {
        x=x*10+ch-'0';
        ch=getchar();
    }
    return x*f;
}
char F[200];
inline void out(I_int x)
{
    if (x == 0) return (void) (putchar('0'));
    I_int tmp = x > 0 ? x : -x;
    if (x < 0) putchar('-');
    int cnt = 0;
    while (tmp > 0)
    {
        F[cnt++] = tmp % 10 + '0';
        tmp /= 10;
    }
    while (cnt > 0) putchar(F[--cnt]);
    //cout<<" ";
}
ll ksm(ll a,ll b,ll p)
{
    //a%=p;
    ll res=1;
    while(b)
    {
        if(b&1)res=1ll*res*a%p;
        a=1ll*a*a%p;
        b>>=1;
    }
    return res;
}
const int inf=0x3f3f3f3f;
const ll mod=1e9+7;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const int maxn=2e5+100,maxm=3e5+7,N=1e6+7;
const double PI = atan(1.0)*4;
vector<int>g[maxn];
ll col[4][maxn];
int n,din[maxn];
int tmp[maxn],res[maxn];
ll ans=-1;
int t[maxn];
///dfs(1,s,-1);
void dfs(int u,int now,int fa){
    if(u>=3) t[u]=6-t[u-1]-t[u-2];
    tmp[now]=t[u];
    ans+=col[tmp[now]][now];
    for(auto t:g[now]){
        if(t==fa) continue;
        dfs(u+1,t,now);
    }
}
int main()
{
    n=read();
    for(int i=1;i<=3;i++)
        for(int j=1;j<=n;j++)
           col[i][j]=read();
    bool flag=1;
    for(int i=1;i<n;i++){
        int u=read(),v=read();
        g[u].push_back(v);
        g[v].push_back(u);
        din[u]++;din[v]++;
        if(din[u]>2||din[v]>2) flag=0;
    }
    if(!flag) puts("-1");
    else{
        int s=-1;
        for(int i=1;i<=n;i++)
            if(din[i]==1){///从头开始遍历
                s=i;break;
            }
        ll minn=INF;
        for(t[1]=1;t[1]<=3;t[1]++)///枚举前两个点的涂色方案
            for(t[2]=1;t[2]<=3;t[2]++)
                if(t[1]!=t[2]){
                    ans=0;
                    dfs(1,s,0);
                    if(minn>ans){
                        minn=ans;
                        for(int i=1;i<=n;i++) res[i]=tmp[i];///更新答案
                    }
                        
                }
        printf("%lld\n",minn);
        for(int i=1;i<=n;i++)
            printf("%d ",res[i]);
    }
    return 0;
}

参考

### Codeforces Round 927 Div. 3 比赛详情 Codeforces是一个面向全球程序员的比赛平台,定期举办不同级别的编程竞赛。Div. 3系列比赛专为评级较低的选手设计,旨在提供更简单的问题让新手能够参与并提升技能[^1]。 #### 参赛规则概述 这类赛事通常允许单人参加,在规定时间内解决尽可能多的问题来获得分数。评分机制基于解决问题的速度以及提交答案的成功率。比赛中可能会有预测试案例用于即时反馈,而最终得分取决于系统测试的结果。此外,还存在反作弊措施以确保公平竞争环境。 ### 题目解析:Moving Platforms (G) 在这道题中,给定一系列移动平台的位置和速度向量,询问某时刻这些平台是否会形成一条连续路径使得可以从最左端到达最右端。此问题涉及到几何学中的线段交集判断和平面直角坐标系内的相对运动分析。 为了处理这个问题,可以采用如下方法: - **输入数据结构化**:读取所有平台的数据,并将其存储在一个合适的数据结构里以便后续操作。 - **时间轴离散化**:考虑到浮点数精度误差可能导致计算错误,应该把整个过程划分成若干个小的时间间隔来进行模拟仿真。 - **碰撞检测算法实现**:编写函数用来判定任意两个矩形之间是否存在重叠区域;当发现新的连接关系时更新可达性矩阵。 - **连通分量查找技术应用**:利用图论知识快速求解当前状态下哪些节点属于同一个集合内——即能否通过其他成员间接相连。 最后输出结果前记得考虑边界条件! ```cpp // 假设已经定义好了必要的类和辅助功能... bool canReachEnd(vector<Platform>& platforms, double endTime){ // 初始化工作... for(double currentTime = startTime; currentTime <= endTime ;currentTime += deltaT){ updatePositions(platforms, currentTime); buildAdjacencyMatrix(platforms); if(isConnected(startNode,endNode)){ return true; } } return false; } ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

豆沙睡不醒

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值