zoukankan      html  css  js  c++  java
  • [HNOI2010]平面图判定

    题意

    一个图是平面图当且仅当所有的边两两不相交(端点除外),现在给定一个带环的图,判定它是不是平面图;多组数据

    思路

    考虑不在环上的边,连接两点的边无非只有两种连法,走环里面或外面,两条边如果可能会有相交部分,就只能一个走外面一个走里面,这显然可以是一个2-SAT问题

    将边当作节点,一条边两个点,分别为走里面和走外面,连边跑tarjan即可

    Code

    #include<bits/stdc++.h>
    #define N 3005
    #define M 100005
    #define Max(x,y) ((x)>(y)?(x):(y))
    #define Min(x,y) ((x)<(y)?(x):(y))
    using namespace std;
    int T,n,m;
    int u[M],v[M],eu[M],ev[M],cir[205][205],ci[N],f[N];
    int dfn[N],low[N],c,col,color[N];
    int st[N],top;
    struct Edge
    {
    	int next,to;
    }edge[M<<2];int head[N],cnt;
    void add_edge(int from,int to)
    {
    	edge[++cnt].next=head[from];
    	edge[cnt].to=to;
    	head[from]=cnt;
    }
    template <class T>
    void read(T &x)
    {
    	char c;int sign=1;
    	while((c=getchar())>'9'||c<'0') if(c=='-') sign=-1; x=c-48;
    	while((c=getchar())>='0'&&c<='9') x=x*10+c-48; x*=sign;
    }
    void init()
    {
    	memset(cir,0,sizeof(cir));
    	memset(dfn,0,sizeof(dfn));
    	memset(color,0,sizeof(color));
    	memset(head,0,sizeof(head));
    	cnt=c=col=top=0;
    }
    void tarjan(int rt)
    {
    	dfn[rt]=low[rt]=++c;
    	st[++top]=rt;
    	for(int i=head[rt];i;i=edge[i].next)
    	{
    		int v=edge[i].to;
    		if(!dfn[v])
    		{
    			tarjan(v);
    			low[rt]=Min(low[rt],low[v]);
    		}
    		else if(!color[v]) low[rt]=Min(low[rt],dfn[v]);
    	}
    	if(dfn[rt]==low[rt])
    	{
    		color[rt]=++col;
    		while(st[top]!=rt) color[st[top--]]=col;
    		--top;
    	}
    }
    void lk()
    {
    	int tot=0;
    	for(int i=1;i<=m;++i) if(!cir[u[i]][v[i]]) eu[++tot]=u[i],ev[tot]=v[i];
    	m=tot;
    	for(int i=1;i<m;++i)
    	{
    		int u1=f[eu[i]],v1=f[ev[i]];
    		if(u1>v1) swap(u1,v1);
    		for(int j=i+1;j<=m;++j)
    		{
    			int u2=f[eu[j]],v2=f[ev[j]];
    			if(u2>v2) swap(u2,v2);
    			if((u1 < u2 && u2 < v1 && v1 < v2) || (u2 < u1 && u1 < v2 && v2 < v1))
    			{
    				add_edge(i,j+m);
    				add_edge(i+m,j);
    				add_edge(j,i+m);
    				add_edge(j+m,i);
    			}
    		}
    	}
    }
    int main()
    {
    	read(T);
    	while(T--)
    	{
    		read(n);read(m);
    		init();
    		for(int i=1;i<=m;++i) read(u[i]),read(v[i]);
    		for(int i=1;i<=n;++i) read(ci[i]),f[ci[i]]=i;
    		for(int i=1;i<n;++i) cir[ci[i]][ci[i+1]]=cir[ci[i+1]][ci[i]]=1;
    		cir[ci[n]][ci[1]]=cir[ci[1]][ci[n]]=1;
    		if(m>3*n-6) { puts("NO"); continue; }
    		
    		lk();
    		for(int i=1;i<=m*2;++i) if(!dfn[i]) tarjan(i);
    		bool no=0;
    		for(int i=1;i<=m;++i) if(color[i]==color[i+m]) no=1;
    		printf(no ? "NO
    " : "YES
    ");
    	}
    	return 0;
    }
    
  • 相关阅读:
    接口测试再思考
    Python开发简单爬虫
    正则表达式(Python)
    Git常用方法
    CNN--卷积神经网络从R-CNN到Faster R-CNN的理解(CIFAR10分类代码)
    一看就懂的K近邻算法(KNN),K-D树,并实现手写数字识别!
    我是这样一步步理解--主题模型(Topic Model)、LDA(案例代码)
    你想知道的特征工程,机器学习优化方法都在这了!收藏!
    从似然函数到EM算法(附代码实现)
    一次性弄懂马尔可夫模型、隐马尔可夫模型、马尔可夫网络和条件随机场!(词性标注代码实现)
  • 原文地址:https://www.cnblogs.com/Chtholly/p/11658777.html
Copyright © 2011-2022 走看看