给定一个弦图,求其最小染色数。

题解

用最大势算法求出弦图的完美消除序列。由于弦图的团数等于其染色数,直接求出其团数即可。

最大势算法详见代码。。

具体的证明可以看 cdq 冬令营的讲课稿。

代码

#include <cstdio>
#include <cstring>
#include <climits>
#include <queue>
#include <algorithm>
const int MAX_N = 10000;
const int MAX_M = 1000000;
struct Node;
struct Edge;
struct Node {
Edge *e;
int pos, label;
bool vis;
Node() : e(NULL), pos(-1), label(0), vis(false) {}
} N[MAX_N + 1];
struct Edge {
Node *fr, *to;
Edge *ne;
Edge(Node *fr, Node *to) : fr(fr), to(to), ne(fr->e) {}
};
inline void addEdge(int fr, int to) {
N[fr].e = new Edge(&N[fr], &N[to]);
N[to].e = new Edge(&N[to], &N[fr]);
}
std::priority_queue< std::pair<int, Node *> > q;
int n, m;
inline int mcs() {
int ans = 0;
for (int i = 1; i <= n; i++) {
q.push(std::make_pair(0, &N[i]));
}
for (int i = n; i >= 1; i--) {
#ifdef DBG
Node *u = q.top().second;
#endif
while (q.top().second->vis) q.pop();
Node *v = q.top().second;
v->pos = i;
v->vis = true;
for (Edge *e = v->e; e; e = e->ne) {
if (!e->to->vis) {
q.push(std::make_pair(++e->to->label, e->to));
}
}
}
for (int i = 1; i <= n; i++) {
int sum = 0;
for (Edge *e = N[i].e; e; e = e->ne) {
if (e->to->pos > N[i].pos) sum++;
}
ans = std::max(ans, sum + 1);
}
return ans;
}
int main() {
scanf("%d %d", &n, &m);
for (int i = 1; i <= m; i++) {
int u, v;
scanf("%d %d", &u, &v);
addEdge(u, v);
}
printf("%d\n", mcs());
return 0;
}