题意:用最少的颜色把图染成任意两个相邻的点颜色不同。
算法:完美消除序列
算法介绍:
首先把图中所有的点标记为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;
}