zoukankan      html  css  js  c++  java
  • 【BZOJ1997】[Hnoi2010]Planar 2-SAT

    【BZOJ1997】[Hnoi2010]Planar

    Description

    Input

    Output

    Sample Input

    2
    6 9
    1 4
    1 5
    1 6
    2 4
    2 5
    2 6
    3 4
    3 5
    3 6
    1 4 2 5 3 6
    5 5
    1 2
    2 3
    3 4
    4 5
    5 1
    1 2 3 4 5

    Sample Output

    NO
    YES

    题解:跟POJ的某熊猫题一模一样?(然而我并没有写那题的题解~)

    本题可以理解为圆上有一些点之间要连线,这些线要么在圆里要么在圆外,问能否让所有的线都不相交。

    直接枚举出每对可能相交的线,然后一个在圆里另一个就必须在圆外,所以从A向B'连边,从B向A'连边就行了。

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    using namespace std;
    int n,m,T,cnt,tot,sum,top;
    int to[1000010],next[1000010],head[2010],dep[2010],low[2010],ins[2010],sta[2010],bel[2010];
    int p[2010],pa[20010],pb[20010];
    int rd()
    {
    	int ret=0,f=1;	char gc=getchar();
    	while(gc<'0'||gc>'9')	{if(gc=='-')f=-f;	gc=getchar();}
    	while(gc>='0'&&gc<='9')	ret=ret*10+gc-'0',gc=getchar();
    	return ret*f;
    }
    void tarjan(int x)
    {
    	dep[x]=low[x]=++tot,ins[x]=1,sta[++top]=x;
    	for(int i=head[x];i!=-1;i=next[i])
    	{
    		if(!dep[to[i]])	tarjan(to[i]),low[x]=min(low[x],low[to[i]]);
    		else	if(ins[to[i]])	low[x]=min(low[x],dep[to[i]]);
    	}
    	if(dep[x]==low[x])
    	{
    		int t;
    		sum++;
    		do
    		{
    			t=sta[top--],ins[t]=0,bel[t]=sum;
    		}while(t!=x);
    	}
    }
    void add(int a,int b)
    {
    	to[cnt]=b,next[cnt]=head[a],head[a]=cnt++;
    }
    void work()
    {
    	memset(head,-1,sizeof(head));
    	memset(dep,0,sizeof(dep));
    	n=rd(),m=rd(),cnt=tot=sum=0;
    	int i,j,a,b;
    	for(i=0;i<m;i++)	pa[i]=rd(),pb[i]=rd();
    	for(i=1;i<=n;i++)	p[rd()]=i;
    	if(m>3*n-6)
    	{
    		printf("NO
    ");
    		return ;
    	}
    	for(i=0;i<m;i++)
    	{
    		pa[i]=p[pa[i]],pb[i]=p[pb[i]];
    		if(pa[i]>pb[i])	swap(pa[i],pb[i]);
    		if(pa[i]+1==pb[i])	continue;
    		for(j=0;j<i;j++)
    		{
    			if(pa[j]+1==pb[j])	continue;
    			if((pa[j]>pa[i]&&pa[j]<pb[i]&&pb[j]>pb[i])||(pa[j]<pa[i]&&pb[j]>pa[i]&&pb[j]<pb[i]))
    				add(i<<1|1,j<<1),add(j<<1|1,i<<1),add(i<<1,j<<1|1),add(j<<1,i<<1|1);
    		}
    	}
    	for(i=0;i<2*m;i++)	if(!dep[i])	tarjan(i);
    	for(i=0;i<m;i++)	if(bel[i<<1]==bel[i<<1|1])
    	{
    		printf("NO
    ");
    		return ;
    	}
    	printf("YES
    ");
    	return ;
    }
    int main()
    {
    	T=rd();
    	while(T--)	work();
    	return 0;
    }
  • 相关阅读:
    tensorflow 2.0 学习 (十) 拟合与过拟合问题
    tensorflow 2.0 学习 (九) tensorboard可视化功能认识
    tensorflow 2.0 学习 (八) keras模块的认识
    tensorflow 2.0 学习 (七) 反向传播代码逐步实现
    tensorflow 2.0 学习 (六) Himmelblua函数求极值
    tensorflow 2.0 学习 (五)MPG全连接网络训练与测试
    arp协议简单介绍
    Pthread spinlock自旋锁
    线程和进程状态
    内核态(内核空间)和用户态(用户空间)的区别和联系·
  • 原文地址:https://www.cnblogs.com/CQzhangyu/p/7044316.html
Copyright © 2011-2022 走看看