• [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;
    }
    
  • 相关阅读:
    JS数字指定长度不足前补零的实现
    IIS7设置将域名不带www跳转到带www上
    NET Core Mvc发布带视图文件的方法!
    NET Core 部署到 Windows服务
    Java配置----JDK开发环境搭建及环境变量配置
    Windows上MyEclipse2017 CI7 安装、破解以及配置
    C# 通过http post 请求上传图片和参数
    MongoDB中的数据导出为excel CSV 文件
    JS计算两个日期之间的天数,时间差计算
    IIS8.5 的环境下添加配置WCF服务!!!!!
  • 原文地址:https://www.cnblogs.com/Chtholly/p/11658777.html
Copyright © 2020-2023  润新知