zoukankan      html  css  js  c++  java
  • bzoj 1997: [Hnoi2010]Planar

    Description

    若能将无向图 G=(V,E)画在平面上使得任意两条无重合顶点的边不相交,则称 G 是平面图。
    判定一个图是否为平面图的问题是图论中的一个重要问题。现在假设你要判定的是一类特殊的
    图,图中存在一个包含所有顶点的环,即存在哈密顿回路。
    输入格式:
    输入文件的第一行是一个正整数T,表示数据组数(每组数据描述一个需要判定的图)。接下来从输入文件第二行开始有T组数据,每组数据的第一行是用空格隔开的两个正整数N和M,分别表示对应图的顶点数和边数。紧接着的M行,每行是用空格隔开的两个正整数u和v(1<=u,v<=n),表示对应图的一条边(u,v),输入的数据保证所有边仅出现一次。每组数据的最后一行是用空格隔开的N个正整数,从左到右表示对应图中的一个哈密顿回路:V1,V2,…,VN,即对任意i≠j有Vi≠Vj且对任意1<=i<=n-1有(Vi,Vi-1) ∈E及(V1,Vn) ∈E。输入的数据保证100%的数据满足T<=100,3<=N<=200,M<=10000。
    输出格式:
    包含T行,若输入文件的第i组数据所对应图是平面图,则在第i行输出YES,否则在第i行输出NO,注意均为大写字母

    solution

    正解:二分图染色
    很容易想到听大佬们说是二分图,然后去分析性质,发现唯一解决矛盾的方法是:
    把相交的两条边的其中一条放到环外面去,然后发现都放出去也会相交,于是就产生了两个集合
    二分图染色判断即可,但是边数是 (m=10000),开不下啊,看了题解,发现有结论:平面图边数不超过 (3*n-6),于是判掉后,边就少了.

    #include <algorithm>
    #include <iostream>
    #include <cstdlib>
    #include <cstring>
    #include <cstdio>
    #include <cmath>
    #define RG register
    #define il inline
    #define iter iterator
    #define Max(a,b) ((a)>(b)?(a):(b))
    #define Min(a,b) ((a)<(b)?(a):(b))
    using namespace std;
    const int N=605,M=605*605*2;
    int n,m,a[N],nxt[M],to[M],num=0,head[N],id[N],col[N],flag=0;
    struct node{int x,y;}e[10005];
    inline void link(int x,int y){
          nxt[++num]=head[x];to[num]=y;head[x]=num;}
    void Clear(){
    	memset(head,0,sizeof(head));num=0;
    	memset(col,0,sizeof(col));flag=1;
    }
    inline void dfs(int x){
    	for(int i=head[x];i;i=nxt[i]){
    		int u=to[i];
    	   if(!col[u]){
    			col[u]=3-col[x];
    			dfs(u);
    		}
    		else if(col[u]==col[x]){flag=0;return ;}
    		if(!flag)return ;
    	}
    }
    void work()
    {
    	Clear();
    	int x1,y1,x2,y2;
    	scanf("%d%d",&n,&m);
    	for(int i=1;i<=m;i++)scanf("%d%d",&e[i].x,&e[i].y);
    	for(int i=1;i<=n;i++)scanf("%d",&a[i]),id[a[i]]=i;
    	if(m>3*n-6){puts("NO");return ;}
    	for(int i=1;i<=m;i++){
    		for(int j=i+1;j<=m;j++){
    			x1=id[e[i].x];y1=id[e[i].y];
    			x2=id[e[j].x];y2=id[e[j].y];
    			if(x1==x2 || x1==y2 || y1==x2 || y1==y2)continue;
    			if(x1>y1)swap(x1,y1);
    			if(x2>y2)swap(x2,y2);
    			if(x1>x2)swap(x1,x2),swap(y1,y2);
    			if(x1<x2 && x2<y1 && y2>y1)link(i,j),link(j,i);
    		}
    	}
    	for(int i=1;i<=m;i++){
    		if(col[i])continue;
    		col[i]=1;dfs(i);
    		if(!flag){puts("NO");return ;}
    	}
    	puts("YES");
    }
    
    int main()
    {
    	int T;cin>>T;
    	while(T--)work();
    	return 0;
    }
    
    
  • 相关阅读:
    Android Studio 开发
    Jsp编写的页面如何适应手机浏览器页面
    电影
    Oracle 拆分列为多行 Splitting string into multiple rows in Oracle
    sql server 2008 自动备份
    WINGIDE 激活失败
    python安装 错误 “User installations are disabled via policy on the machine”
    ble编程-外设发送数据到中心
    iOS开发-NSString去掉所有换行及空格
    ios9 字符串与UTF-8 互相转换
  • 原文地址:https://www.cnblogs.com/Yuzao/p/7967092.html
Copyright © 2011-2022 走看看