Codeforces Round #411 (Div. 2) E(特殊条件下使用dfs着色)

Codeforces Round #411 (Div. 2) E

题意:

有一棵树T有n个结点,有m种冰淇淋。T中每个结点有一些种类的冰淇淋,也有可能没有冰淇淋。拥有同一种冰淇淋的结点构成联通子图。没有冰淇淋的结点也构成联通子图。

现在创建一个图G,有m个结点,对应m种冰淇淋。如果有u,v两种冰淇淋同时出现在T的某个结点中,就在G中增加边uv。要给图G着色,使得相邻的点颜色不相同,且使用的颜色总数最少,求染色方案。

 

思路:

先说结论,我们只要搜索树中每一个结点,对于当前节点中未染色的点,贪心地使用尽可能小、而又不和当前的节点中已经使用过的颜色冲突的颜色来染即可。原因是题目中特殊条件:在树T中,拥有相同种类冰淇淋的结点构成联通子图。这样可以反证,当前贪心选择最小的颜色来染,一定不会在新图G中和它相邻结点的颜色发生冲突。

#include <bits/stdc++.h>

using namespace std;

const int mx = 3e5 + 10;
int n, m, ans = 0;
int color[mx];
int in[mx];
bool colored[mx], vis[mx];
vector<int> s[mx];
vector<int> t[mx];
vector<int> v1, v2;//待着色 已着色

void init(){
    cin >> n >> m;
    for(int i = 1; i <= n; i++){
        int len; scanf("%d", &len);
        if(len > ans)  ans = len;
        while(len--){
            int tmp; scanf("%d", &tmp);
            s[i].push_back(tmp);
        }
    }
    for(int i = 1; i < n; i++){
        int u, v;
        scanf("%d %d", &u, &v);
        t[u].push_back(v);
        t[v].push_back(u);
    }
}

void dfs(int u){
    vis[u] = true;
    v1.clear(); v2.clear();
    for(int i = 0; i < s[u].size(); i++){
        int tnode = s[u][i];
        if(!color[tnode]) v1.push_back(tnode);
        else {
            v2.push_back(tnode);
            colored[color[tnode]] = true;
        }
    }
    int c = 1;
    for(int i = 0; i < v1.size(); i++){
        while(colored[c]) c++;
        color[v1[i]] = c++;
    }
    for(int i = 0; i < v2.size(); i++){
        colored[color[v2[i]]] = false;
    }
    for(int i = 0; i < t[u].size(); i++)
        if(!vis[t[u][i]]) dfs(t[u][i]);
}

void solve(){
    dfs(1);
    if(!ans){
        cout << 1 << endl;
        for(int i = 1; i <= m; i++)
            printf("1 ");
        printf("\n");
    }
    else{
        cout << ans << endl;
        for(int i = 1; i <= m; i++)
            printf("%d ", max(color[i], 1));
        printf("\n");
    }
}

int main()
{
    init();
    solve();
    return 0;
}

 

 

问题: 用bfs会有什么问题吗?
[Wèntí: Yòng bfs huì yǒu shé me wèntí ma?]
problem:

Is there any problem with bfs?
 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值