• Codeforces 776 F. Sherlock's bet to Moriarty(平面图转对偶图+点分治染色)


    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;
    }
    
  • 相关阅读:
    JavaScript 执行机制
    前端问题总结
    【2020 -02- 07】组件与模板
    【2020-02-07】组件与模板
    【2020-01-23】组件与模板 -- 模板语法
    关于java.lang.UnsatisfiedLinkError的处理
    两个Activity传递数据和对象
    Android Activity为什么要细化出onCreate、onStart、onResume、onPause、onStop、onDesdroy这么多方法让应用去重载?(转)
    通过Android Studio 导出Jar包
    关于AccessibilityService的用法(转)
  • 原文地址:https://www.cnblogs.com/coldchair/p/13046714.html
Copyright © 2020-2023  润新知