1006: [HNOI2008]神奇的国度[完美消除序列MCS]

6 篇文章 0 订阅
1 篇文章 0 订阅

题意:用最少的颜色把图染成任意两个相邻的点颜色不同。


算法:完美消除序列
算法介绍:
首先把图中所有的点标记为0,然后找一个点入队,每次队头元素为标记最大的点即要消除的点,对于消除的点,我们要与他相连的点标记+1,然后没有消除的点入队。


题解:
我们根据MCS的过程模拟一下本题。
原图:
在这里插入图片描述
此时所有的标记都为0;
下面我们消除1
在这里插入图片描述
2和4的标记+1变为1
然后我们选择2进行下一次的消除
在这里插入图片描述
此时3的标记为1,4的标记为2,所以下一次一定要消除4
在这里插入图片描述

然后最后消除3
此时标记的种类有 { 0 , 1 , 2 , 1 } \{0, 1, 2, 1\} {0,1,2,1}可以看到用了三个标记,所以使用三种颜色即可消除所有的点。


a c   c o d e : ac\ code: ac code:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define met(a, b) memset(a, b, sizeof(a))
#define rep(i, a, b) for(int i = a; i <= b; i++)
#define per(i, a, b) for(int i = a; i >= b; i--)
#define pii pair<int, int>
const int maxn = 1e5 + 10;
const int inf = 0x3f3f3f3f;
inline int read() {
    int 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 f * x;
}

class Bzoj1006 {
public:
    void init() {
        met(use, false);
        met(vis, false);
        ans = 0;
        met(cnt, 0);
    }
    void input() {
        init();
        int u, v;
        n = read(), m = read();
        G = new vector<int>[maxn];
        rep(i, 1, m) {
            u = read(); v = read();
            G[u].push_back(v);
            G[v].push_back(u);
        }
    }

    void solve() {
        priority_queue<pair<int, int> > * q = new priority_queue<pair<int, int> >;
        while(!q -> empty()) q -> pop();
        rep(i, 1, n) q -> push(pii(0, i));
        while(!q -> empty()) {
            while(!q -> empty() && vis[q -> top().second]) q -> pop();
            if(q -> empty()) break;
            int u = q -> top().second;
            q -> pop();
            //cout << u << endl;
            vis[u] = true;
            if(!use[cnt[u]]) {
                ans++;
                use[cnt[u]] = true;
            }
            int len = G[u].size();
            rep(i, 0, len - 1) {
                int v = G[u][i];
                if(vis[v]) continue;
                cnt[v]++;
                q -> push(pii(cnt[v], v));
            }
        }
        printf("%d\n", ans);
        delete q;
    }

private:
    vector<int> *G;
    int n, m, ans, cnt[maxn];
    bool vis[maxn], use[maxn];
};

int main() {
    Bzoj1006 * pro = new Bzoj1006;
    pro -> input();
    pro -> solve();
    delete pro;
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值