1.题目描述:
给你一个连通图,对它进行染色,某节点的颜色和他的相邻节点颜色不能相同,且对于每个父亲,它所有儿子的颜色都不能相同,问你最少需要多少颜色
3.解题思路:
很经典的染色问题,建图方法很多,可以vector也可以链式前向星,从任意节点开始dfs,每代记录和当代和父代的节点标号,这样可以保证当代的子代颜色与两者都不相同,接下来就是染色了,当时想的时候是vis记录颜色使用情况,现在想想大可不必,直接用cnt记录就好,注意的是,把当代所有儿子都染色完以后再去对儿子进行dfs。感觉bfs也是可以做的,以后再想咯。
更新:
这道题性质是对于每个父亲,所有儿子的颜色不同,而bfs性质又是要对父亲进行bfs,这样就不能保证当前是父亲,下一步对儿子染色时能有传递性了,除非另外记录上一步转移过来的颜色,最好做法是DFS。而如果只要求相邻节点颜色不同,则做法可以是bfs贪心地选颜色,具体题型参见UVA1613。
4.AC代码:
#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
#define maxn 200100
#define N 1111
#define eps 1e-6
#define pi acos(-1.0)
#define e exp(1.0)
using namespace std;
const int mod = 1e9 + 7;
typedef long long ll;
typedef unsigned long long ull;
vector<int> G[maxn];
int color[maxn];
void dfs(int cur, int pre)
{
int cnt = 1;
for (int i = 0; i < (int)G[cur].size(); i++)
if (G[cur][i] != pre) //子父颜色不同
{
while (cnt == color[cur] || cnt == color[pre])
cnt++;
color[G[cur][i]] = cnt++; //染色
}
//先把当代儿子染完色再dfs
for (int i = 0; i < (int)G[cur].size(); i++)
if (G[cur][i] != pre)
dfs(G[cur][i], cur);
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
long _begin_time = clock();
#endif
int n;
while (~scanf("%d", &n))
{
for (int i = 1; i <= n; i++)
G[i].clear();
for (int i = 0; i < n - 1; i++)
{
int u, v;
scanf("%d%d", &u, &v);
G[u].push_back(v);
G[v].push_back(u);
}
memset(color, 0, sizeof(color));
color[1] = 1;
dfs(1, 0);
int ans = 0;
for (int i = 1; i <= n; i++)
ans = max(ans, color[i]);
printf("%d\n", ans);
for (int i = 1; i <= n; i++)
if (i == 1)
printf("%d", color[i]);
else
printf(" %d", color[i]);
puts("");
}
#ifndef ONLINE_JUDGE
long _end_time = clock();
printf("time = %ld ms.", _end_time - _begin_time);
#endif
return 0;
}