• CodeForces 1244D. Paint the Tree


    题意:树是一个无向联通的无环图,现在给你一棵树,你有三种不同的颜色1,2,3可以选择,你要把树上的每个点涂一种颜色,使得任何一条由三个不同的点构成的路(这一段路上只能有三个点,就是0-0-0),他们之间的颜色是不同的。现在给你三种颜色,每种颜色染每个点需要的花费。请你给出一种染色的方案,满足以上条件使总花费最小。

    分析:我们可以发现,不合法的情况是一个点连了大于等于3个点,即存在一个点的度数是大于等于3的。然后我们可以发现整个树是一条链,意味着当我们确定两个相邻的点的颜色后,其它点的颜色可以根据这两个点的颜色全部推出,比如p1点为a颜色,p2点为b颜色,那么第三个点的颜色为6 - a - b,我们只要遍历一下树,就可以推出所有颜色值。

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <string>
    #include <algorithm>
    
    using namespace std;
    using LL = long long;
    const int N = 100005;
    int h[N], e[2 * N], ne[2 * N], idx;
    int c[4][N];
    int g[N], f[N];
    int d[N];
    
    void add(int a, int b)
    {
    	e[idx] = b, ne[idx] = h[a], h[a] = idx++;
    }
    
    LL dfs(int u, int fa, int color)
    {
    	g[u] = color;
    
    	LL cost = c[color][u];
    	for (int i = h[u]; i != -1; i = ne[i])
    	{
    		int j = e[i];
    		if (j == fa) continue;
    		cost += dfs(j, u, 6 - g[u] - g[fa]);
    	}
    	return cost;
    }
    LL cal(int a, int b)
    {
    	LL cost = 0;
    	g[1] = a;
    	cost += c[a][1];
    	int p2;
    	for (int i = h[1]; i != -1; i = ne[i])
    	{
    		int j = e[i];
    		p2 = j;
    		cost += c[b][p2];
    		break;
    	}
    	g[p2] = b;
    
    	int p1 = 1;
    
    	for (int i = h[p1]; i != -1; i = ne[i])
    	{
    		int j = e[i];
    		if (j == p2) continue;
    		cost += dfs(j, p1, 6 - a - b);
    	}
    
    	for (int i = h[p2]; i != -1; i = ne[i])
    	{
    		int j = e[i];
    		if (j == p1) continue;
    		cost += dfs(j, p2, 6 - a - b);
    	}
    	return cost;
    }
    
    int main()
    {
    	int n;
    	scanf("%d", &n);
    
    	for(int i = 1; i <= 3; ++i)
    		for (int j = 1; j <= n; ++j)
    		{
    			scanf("%d", &c[i][j]);
    		}
    
    	memset(h, -1, sizeof h);
    
    	int u, v;
    	for (int i = 1; i < n; ++i)
    	{
    		scanf("%d%d", &u, &v);
    		++d[u], ++d[v];
    		add(u, v), add(v, u);
    	}
    
    	bool flag = true;
    	for (int i = 1; i <= n; ++i)
    	{
    		if (d[i] >= 3)
    		{
    			flag = false;
    			break;
    		}
    	}
    
    	if (!flag)
    	{
    		cout << -1 << endl;
    	}
    	else
    	{
    		LL mx = 1e18;
    		for (int i = 1; i <= 3; ++i)
    		{
    			for (int j = 1; j <= 3; ++j)
    			{
    				if (j != i)
    				{
    					LL cost = cal(i, j);
    					if (mx > cost)
    					{
    						mx = cost;
    						for (int k = 1; k <= n; ++k)
    							f[k] = g[k];
    					}
    				}
    			}
    		}
    		cout << mx << endl;
    		for (int i = 1; i <= n; ++i)
    			cout << f[i] << " ";
    	}
    
    	
    
    	return 0;
    }
    
  • 相关阅读:
    Levenshtein距离
    最长上升子序列
    python常用内置方法
    【转载】一个有趣的python排序模块:bisect
    python常用内置函数
    线性相位FIR系统的单位脉冲响应
    模拟信号与数字信号的傅里叶变换的关系
    从傅里叶级数到傅里叶变换
    完善实体类,由EF自动生成数据库过程中的一些问题
    成为NB程序员的“关键”
  • 原文地址:https://www.cnblogs.com/pixel-Teee/p/13232433.html
Copyright © 2020-2023  润新知