首页 > 其他分享 >[HNOI2010] 平面图判定-平面图性质、带权并查集/2-sat

[HNOI2010] 平面图判定-平面图性质、带权并查集/2-sat

时间:2023-10-22 22:22:05浏览次数:51  
标签:geq rep 查集 平面图 leq second 带权

[HNOI2010] 平面图判定-平面图性质、带权并查集/2-sat

https://www.luogu.com.cn/problem/P3209

题意:给一张 \(n\) 个点,\(m\) 条边的哈密顿图,并且哈密顿回路已知,问是否是平面图,\(T\) 组询问。

\(1\leq T\leq 100,1\leq n\leq 200,1\leq m\leq 10^4\)。


转换挺奇妙的。

极大平面图

《离散数学》这课的高光时刻来了,没想到结课之后居然还会翻课件…

首先欧拉示性数公式告诉我们,一张简单的连通的平面图,点数 \(n\),边数 \(m\) 和面数 \(f\) 有关系 \(n-m+f=2\)。

如果连通分支的个数变成 \(k\) 个,则不难发现,修正后的结果是

\[n-m+f=k+1 \]

定理1.设 \(G\) 是连通的平面图,\(deg(R_i)\geq l\geq 3\),则 \(m\leq \frac{l}{l-2}(n-2)\),其中 \(R_i\) 表示平面图中的平面,\(deg(R_i)\) 则表示 \(R_i\) 这个平面的边数

证:有类似于握手定理的 \(2m=\sum deg(R_i)\geq l\times f\geq l(2-n+m)\),即有

\[2m\geq ml+l(2-n) \]

化简得到 \((2-l)m\geq l(2-n)\),因为 \(l\geq 3\),所以 \(m\leq \frac{l}{l-2}(n-2)\).

定理2. 设 \(G\) 是简单平面图,且\(n\geq 3\) 则 \(m\leq 3n-6\)。

证:假设有 \(k\) 个连通分支,如果 \(G\) 是森林,则 \(m\leq n-1\leq 3n-6\)(当 \(n\geq 3\) ),否则 \(G\) 的某个连通分支有环,而简单图的环至少是三元环,因此这个子图有 \(m\leq \frac{3}{1}(n-k-1)=3(n-2)\).

并查集

所以这题虽然 \(m\) 取到了 \(10^4\) ,但其实只有 \(m\leq 3n-6<300\) 才需要判断。

  • 而对于 \(m\) 小的情况,因为哈密顿回路已经给出了,所以先把点按照其在哈密顿回路上的顺序排好。

  • 再考虑任意两条边,如果位置存在交叉的情况,那么一定是一个在内侧,一个在外侧的,就转化成了一个 2-sat 的模型。

  • 但仔细一想,这个排斥关系是相互的(即如果我们考虑2-sat的建图,就会变成:如果 \(i\to j\) 有边,那么 \(j\to i\) 也有边),所以其实是个无向图

  • 所以直接用带权并查集就行了。

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define endl '\n'
#define fastio ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0)
using namespace std;
const int N=205;
namespace DSU{
	int fa[N*3],dep[N*3],bad;
	int find(int x){
		if(fa[x]==x)return x;
		int t=dep[fa[x]];	//这里注意一下要先把压缩前的距离存下来
		fa[x]=find(fa[x]);
		dep[x]^=t;
		return fa[x];
	}
	void init(int n){
		bad=0;
		rep(i,0,n-1)fa[i]=i,dep[i]=0;
	}
	void merge(int x,int y){
		int fx=find(x),fy=find(y);
		if(fx==fy){
			if(dep[x]==dep[y])bad=1;
			return ;
		}
		fa[fy]=fx;
		dep[fy]=(dep[x]^dep[y]^1);
	}
};
int n,m,v[N],pos[N];
vector<pair<int,int>> E;
int main(){
	fastio;
	int tc;cin>>tc;
	while(tc--){
		cin>>n>>m;
		E.resize(m);
		rep(i,0,m-1)cin>>E[i].first>>E[i].second;
		m=E.size();
		rep(i,1,n)cin>>v[i];
		if(m>3*n-6)cout<<"NO"<<endl;
		else{
			rep(i,1,n)pos[v[i]]=i;
			rep(i,0,m-1){
				E[i].first=pos[E[i].first];
				E[i].second=pos[E[i].second];
				if(E[i].first>E[i].second)swap(E[i].first,E[i].second);
			}
			DSU::init(m);
			rep(i,0,m-1){
				int l=E[i].first,r=E[i].second;
				rep(j,i+1,m-1){
					int p=E[j].first,q=E[j].second;
					if((l<p&&p<r&&r<q)||(p<l&&l<q&&q<r))DSU::merge(i,j);//两种都要判
				}
			}
			if(DSU::bad)cout<<"NO"<<endl;
			else cout<<"YES"<<endl;
		}
	}
	return 0;
}

标签:geq,rep,查集,平面图,leq,second,带权
From: https://www.cnblogs.com/yoshinow2001/p/17781284.html

相关文章

  • 关于并查集的感受
    什么情况下2个节点还没加入一个集合就已经在一个集合了?就说明如果把这2个节点画进图里连起来,那么一定构成了一个环。举个简单的栗子 对于join函数,只要加入了2个节点,那么至少这两个节点就构成了1个集合,如果还没加入它们就以及有同一个根节点了那么就说明对应的图里存在环,如果......
  • 种类并查集
    P1892[BOI2003]团伙如果你wa,可能是合并的顺序出错[1,n]表示朋友,[n+1,2*n]表示敌人如果a,b是朋友,直接合并a,b如果a,b是敌人:1.合并a+n和b,a的敌人是b的朋友2.合并a和b+n,b的敌人是a的朋友点击查看代码#include<bits/stdc++.h>usingnamespacestd;intf[20005];intd[20......
  • 并查集
    并查集的原理来自百度百科并查集,在一些有N个元素的集合应用问题中,我们通常是在开始的时候让每个元素构成单个元素的集合,然后按一定顺序讲属于同一组的元素所在集合合并,期间要反复查询一个元素在哪个集合中。描述改问题的抽象数据结构为并查集。并查集是一种树型的数据结构,用于处理......
  • 并查集学习指南
    前置芝士并查集思想[find][python]#pythonwhiledeffind(x:int)->int: whilex!=fa[x]: x=fa[x]=fa[fa[x]] returnx#python递归deffind(x:int)->int: iffa[x]!=x: fa[x]=find(fa[x]) returnfa[x][c++]//c++whilelambda/*function<int(int)>fi......
  • [算法分析与设计] 3. 并查集分析与反阿克曼函数
    Union-Find问题:给定\(n\)个元素,最初每个元素在一个集合中,有两种操作,union表示合并两个集合,find表示查询某个特定元素所在的集合。并查集是一种数据结构。其为每个集合寻找一个代表元,代表元可以是任意的,也可以随操作变化,但需要满足任何时刻一个集合的代表元是确定且唯一的。......
  • 并查集
    并查集如果有一个关系网,我们需要建立两点之间的关系,如果仅用一维链表,则有可能无法考虑到两点同为一点“儿子”的情况,则我们需要建立一个方式,从而直接对比两点“祖父”。一.递归查询intfind(intx){ if(fa[x]==x)returnx;//只有祖父自环,如果他也自环,则找到父节点 ......
  • 并查集的实现【学习算法】
    并查集的实现【学习算法】前言版权推荐并查集的实现最后前言2023-9-2614:38:02以下内容源自《【学习算法】》仅供学习交流使用版权禁止其他平台发布时删除以下此话本文首次发布于CSDN平台作者是CSDN@日星月云博客主页是禁止其他平台发布时删除以上此话推荐算法讲解056【必备】并......
  • 动态规划——带权二分优化DP 学习笔记
    动态规划——带权二分优化DP学习笔记引入带权二分其实并不一定用于优化DP,也可能用于优化贪心等最优化的算法。带权二分也叫WQS二分,最初由王钦石在他的2012年国家集训队论文中提出。定义使用情况要解决一个最优化问题(求最大/最小值)有一个限制,一般是某个参数要求一......
  • 并查集
    基本的并查集OI-wikiLink并查集,一种用于管理元素所属集合的数据结构,形如一片森林,同一棵树内的元素所属同一集合,不同树内的元素不属于同一集合。将并查集拆分一下。并,合并;查,查询;集,处理的是集合相关内容。所以并查集一共有两种操作:合并两元素对应集合、查询某元素所属集合(查......
  • 数据结构-并查集
    并查集的使用范围:1.合并集合2.查询两元素是否属于同一集合   高级用法:  3.进行集合划分<带权并查集>  4.连通块块数查询&块内元素个数统计<连通图>  5.撤销合并<可持久化并查集>//本文暂不涉及,我还不会并查集基本操作:#definerep(i,n)for(int......