• BZOJ1997 HNOI2010 平面图判定 planar (并查集判二分图)


    题意

    判断一个存在哈密顿回路的图是否是平面图。
    n200,m10000nle200,mle10000

    题解

    如果一定存在一个环,那么连的边要么在环里面要么在外面。那么把在同侧会矛盾的边之间连边,如果是一个二分图就是平面图。

    有问题的是边数是O(m2)O(m^2)的。但是可以发现当m>n36m>n*3-6的时候一定形成不了平面图。所以就判一下,如果小于等于就O(m2)O(m^2)做。

    证明:先画出一条环,有nn条边,然后这个环的一个点向非相邻的n3n-3个点连接n3n-3条边可以保证两两不相交,外面一侧如此,故如果边数m>n36m>n*3-6,就直接判断NONO即可。保证了复杂度。

    判二分图的方法可以用带权并查集或者直接染色,这里写的是带权并查集。

    CODE

    #include <bits/stdc++.h>
    using namespace std;
    inline void rd(int &x) {
    	char ch; for(;!isdigit(ch=getchar()););
    	for(x=ch-'0';isdigit(ch=getchar());)x=x*10+ch-'0';
    }
    const int MAXN = 205;
    const int MAXM = 10005;
    int n, m, u[MAXM], v[MAXM], seq[MAXN], id[MAXN];
    int d[MAXM], fa[MAXM];
    int find(int x) {
    	if(x != fa[x]) {
    		int old = fa[x];
    		fa[x] = find(fa[x]);
    		d[x] ^= d[old];
    	}
    	return fa[x];
    }
    int main() {
    	int T; rd(T); while(T--) {
    		rd(n), rd(m);
    		for(int i = 1; i <= m; ++i) rd(u[i]), rd(v[i]);
    		for(int i = 1; i <= n; ++i) rd(seq[i]), id[seq[i]] = i;
    		if(m > 3*n-6) puts("NO");
    		else {
    			bool flg = 1;
    			for(int i = 1; i <= m && flg; ++i) {
    				fa[i] = i; d[i] = 0;
    				int l = min(id[u[i]], id[v[i]]);
    				int r = max(id[u[i]], id[v[i]]);
    				for(int j = 1; j < i && flg; ++j)
    					if(id[u[j]] != l && id[u[j]] != r && id[v[j]] != l && id[v[j]] != r && ((l <= id[u[j]] && id[u[j]] <= r)^(l <= id[v[j]] && id[v[j]] <= r))) {
    						int u = find(i), v = find(j);
    						if(u == v) flg &= (d[i] != d[j]);
    						else fa[u] = v, d[u] = d[i] ^ d[j] ^ 1;
    					}
    			}
    			puts(flg ? "YES" : "NO");
    		}
    		
    	}
    }
    
  • 相关阅读:
    github创建repo,本地导入git项目到github
    成功的GIT开发分支模型和策略
    示例可重用的web component方式组织angular应用模块
    git deployment strategy
    如何在linux中从源代码编译安装nodejs?
    some resource favor
    学而习之,成就学习
    C# 去掉代码前边空格(格式化代码)
    mvc重定向
    mvc cshtml 中赋值
  • 原文地址:https://www.cnblogs.com/Orz-IE/p/12039198.html
Copyright © 2020-2023  润新知