• Codeforces 223E. Planar Graph(平面图)


    http://codeforces.com/problemset/problem/223/E

    题解:

    本题做法:
    因为是个连通图,可以神奇的转换:
    1.有一汇点T,每个点有一个流量朝汇点流,可以发现每个点的出流-入流=1(自己多的1)
    2.从汇点T开始dfs,随便保留一个生成树作为流量树,发现一条边流量等于子树点数
    3.对于一个环,它的内部点数=出去外面的流量-从外面来的流量
    4.对环上每个点,把出边按几角排好序,预处理前缀和,在上面二分即可得到答案。

    更加通用的做法:
    1.平面图转对偶图
    2.平面图欧拉公式:V+F=E+2
    2.一个平面图环内的点数,=对偶图上删掉对应的边,环围成的点所在联通块的边数+2-点数。
    3.相当于每条边有一个存在时间,查询一个时间一个点的联通块的边数和点数,经典分治+可撤销并查集即可解决。

    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 = 3e5 + 5;
    
    #define db double
    
    int n, m, x, y;
    
    vector<int> e[N];
    #define pb push_back
    #define si size()
    
    struct P {
    	db x, y;
    	P(db _x = 0, db _y = 0) {
    		x = _x, y = _y;
    	}	
    } a[N];
    
    P operator + (P a, P b) { return P(a.x + b.x, a.y + b.y);}
    P operator - (P a, P b) { return P(a.x - b.x, a.y - b.y);}
    db operator ^ (P a, P b) { return a.x * b.y - a.y * b.x;}
    db operator * (P a, P b) { return a.x * b.x + a.y * b.y;}
    P operator * (P a, db b) { return P(a.x * b, a.y * b);}
    
    int fa[N], bz[N], siz[N];
    
    db ang(P a, P b) {
    	return atan2(b.y - a.y, b.x - a.x);
    }
    
    vector<P> s[N];
    
    int cmpe(P a, P b) {
    	return a.x < b.x;
    }
    
    int d[N], d0;
    
    void dg(int x) {
    	d[d0 = 1] = x; bz[x] = 1;
    	for(int i = 1; i <= d0; i ++) {
    		int x = d[i];
    		ff(_y, 0, e[x].si) {
    			int y = e[x][_y];
    			if(bz[y]) continue;
    			fa[y] = x;
    			bz[y] = 1;
    			d[++ d0] = y;
    		}
    	}
    	fd(i, d0, 1) {
    		int x = d[i];
    		siz[x] = 1;
    		ff(_y, 0, e[x].si) {
    			int y = e[x][_y];
    			if(fa[y] != x) continue;
    			siz[x] += siz[y];
    			s[x].pb(P(ang(a[x], a[y]), -siz[y]));
    		}
    		if(fa[x] <= n) {
    			s[x].pb(P(ang(a[x], a[fa[x]]), siz[x]));
    		}
    		if(s[x].si) {
    			sort(s[x].begin(), s[x].end(), cmpe);
    			ff(j, 1, s[x].si) s[x][j].y += s[x][j - 1].y;
    		}
    	}
    }
    
    void build() {
    	int t = 1;
    	fo(i, 2, n) if(a[i].x < a[t].x) t = i;
    	e[n + 1].pb(t); e[t].pb(n + 1);
    	dg(n + 1);
    }
    
    int Q, k;
    P b[N]; int c[N];
    
    void check_order() {
    	db s = 0;
    	fo(i, 2, k - 1) s += (b[i] - b[1]) ^ (b[i + 1] - b[1]);
    	if(s < 0) {
    		reverse(b + 1, b + k + 1);
    		reverse(c + 1, c + k + 1);
    	}
    }
    
    const db pi = acos(-1);
    
    const db eps = 1e-11;
    
    ll ef(vector<P> &s, db p) {
    	int as = -1;
    	for(int l = 0, r = s.si - 1; l <= r; ) {
    		int m = l + r >> 1;
    		if(s[m].x <= p) as = m, l = m + 1; else r = m - 1;
    	}
    	if(as == -1) return 0;
    	return s[as].y;
    }
    
    ll solve(int x, db p, db q) {
    	ll ans = 0;
    	if(fa[x] > n) ans += siz[x];
    	if(s[x].si == 0) return ans;
    	if(p <= q) ans += ef(s[x], p - eps) + (s[x][s[x].si - 1].y - ef(s[x], q + eps)); else
    		ans += ef(s[x], p - eps) - ef(s[x], q + eps);
    	return ans;
    }
    
    int main() {
    	freopen("graph.in", "r", stdin);
    	freopen("graph.out", "w", stdout);
    	scanf("%d %d", &n, &m);
    	fo(i, 1, m) {
    		scanf("%d %d", &x, &y);
    		e[x].pb(y); e[y].pb(x);
    	}
    	fo(i, 1, n) scanf("%lf %lf", &a[i].x, &a[i].y);
    	build();
    	scanf("%d", &Q);
    	fo(ii, 1, Q) {
    		scanf("%d", &k);
    		fo(i, 1, k) {
    			scanf("%d", &c[i]);
    			b[i] = a[c[i]];
    		}
    		check_order();
    		ll ans = 0;
    		fo(i, 1, k) {
    			ans += solve(c[i], ang(b[i], i == k ? b[1] : b[i + 1]), ang(b[i], i == 1 ? b[k] : b[i - 1]));
    		}
    		pp("%lld
    ", ans);
    	}
    }
    
  • 相关阅读:
    Jenkins和Postman 集成,使用Allure 输出测试报告
    Jenkins 中使用VSTest.console 进行单元测试,使用Allure 输出测试报告
    如果网页中有ShawdowDOM ,如何使用 Selenium Web Driver 进行操作
    postman 不能打开
    chrome DEvTools 使用
    使用selenium 连接到一个已经打开的浏览器
    如何查看电脑开关机时间
    Task.Wait() 和 await Task 的区别
    已经过了1/3的2020
    Laravel7 配置jwt ,并处理 Unauthorized 错误
  • 原文地址:https://www.cnblogs.com/coldchair/p/13033321.html
Copyright © 2020-2023  润新知