https://codeforces.com/contest/776/problem/F
题解:
-
好像很久没写平面转对偶了,当板题写一写。
-
发现多边形内的对偶图是棵树,因为如果有m条边,则有m+1个域,m+1个点m条边的连通图一定是树。
-
第一个思考点是标号,发现这道题中两个域最多只有一个公共点,所以排好序后直接字典序比较即可,如果是其它的话,应该可以写trie来排序。
-
第二个思考点是染色,发现给它们染上点分树上的深度就好了,两个同深度的点的路径一定会经过更低深度的点。
Code:
#include<bits/stdc++.h>
#define fo(i, x, y) for(int i = x, _b = y; i <= _b; i ++)
#define ff(i, x, y) for(int i = x, _b = y; i < _b; i ++)
#define fd(i, x, y) for(int i = x, _b = y; i >= _b; i --)
#define ll long long
#define pp printf
#define hh pp("
")
using namespace std;
const int N = 8e5 + 5;
int n, m;
int x, y;
int tot = 1, fi[N], nt[N], to[N], fr[N];
void link(int x, int y) {
nt[++ tot] = fi[x], to[tot] = y, fr[tot] = x, fi[x] = tot;
}
#define pii pair<int, int>
#define fs first
#define se second
int tra[N];
int bz[N], td;
vector<int> t[N];
#define pb push_back
#define si size()
int cmpt(int x, int y) { return x > y;}
void bfs(int x) {
static int d[N], d0;
int st = fr[x]; d[d0 = 1] = x;
for(int i = 1; i <= d0; i ++) {
int x = d[i];
if(to[x] == st) break;
d[++ d0] = tra[x];
}
td ++;
fo(i, 1, d0) {
bz[d[i]] = td;
t[td].pb(to[d[i]]);
}
sort(t[td].begin(), t[td].end(), cmpt);
}
int p[N];
int cmpd(int x, int y) {
ff(j, 0, t[x].si) {
if(t[x][j] > t[y][j]) return 0;
if(t[x][j] < t[y][j]) return 1;
}
}
void lsp() {
static int d[N];
fo(i, 1, td) d[i] = i;
sort(d + 1, d + td + 1, cmpd);
fo(i, 1, td) p[d[i]] = i;
}
vector<int> e[N];
int cr[N];
namespace fz {
int siz[N], bz[N], G, mx[N];
void fg(int x) {
bz[x] = 1;
siz[x] = 1; mx[x] = 0;
ff(_y, 0, e[x].si) {
int y = e[x][_y]; if(bz[y]) continue;
fg(y);
siz[x] += siz[y];
mx[x] = max(mx[x], siz[y]);
}
mx[x] = max(mx[x], siz[0] - siz[x]);
if(mx[x] < mx[G]) G = x;
bz[x] = 0;
}
void dg(int D, int x) {
fg(x);
cr[x] = D;
bz[x] = 1;
ff(_y, 0, e[x].si) {
int y = e[x][_y]; if(bz[y]) continue;
siz[0] = siz[y], G = 0, fg(y);
dg(D + 1, G);
}
}
void work() {
siz[0] = mx[0] = td, G = 0, fg(1);
dg(1, G);
}
}
int main() {
scanf("%d %d", &n, &m);
fo(i, 1, m) {
scanf("%d %d", &x, &y);
link(x, y); link(y, x);
}
fo(i, 1, n) {
int j = i == n ? 1 : i + 1;
link(i, j); link(j, i);
}
fo(i, 1, n) {
static pii d[N]; static int d0 = 0;
d0 = 0;
for(int j = fi[i]; j; j = nt[j])
d[++ d0] = pii(to[j], j);
sort(d + 1, d + d0 + 1);
fo(j, 1, d0) {
int k = j == d0 ? d[1].se : d[j + 1].se;
tra[d[j].se ^ 1] = k;
}
}
fo(i, 2, tot) if(!bz[i]) {
if(to[i] == fr[i] % n + 1) continue;
bfs(i);
}
lsp();
for(int i = 2; i <= tot; i += 2) {
if(bz[i] && bz[i ^ 1]) {
int x = p[bz[i]], y = p[bz[i ^ 1]];
e[x].pb(y); e[y].pb(x);
}
}
fz :: work();
fo(i, 1, td) pp("%d ", cr[i]); hh;
}