[BZOJ1997] [Hnoi2010]Planar - 2-SAT

1997: [Hnoi2010]Planar

Time Limit: 10 Sec  Memory Limit: 64 MB
Submit: 2639  Solved: 1015
[Submit][Status][Discuss]

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

HINT

 


 

 

题解:

2—SAT裸题...

如果两条边i,j有相交,那么我们创造一个命题"如果i则~j",逆否命题"如果j则~i",然后裸了...

 


 

 

Code

 

#include <iostream>
#include <cstdio>
#include <vector>
#include <cstring>
using namespace std;
int T, n, m; 
int L[10010], R[10010], num;
struct edge{
    int nxt,to;
}ed[1000005];
int head[5005], cnt = 1;
inline void add(int x, int y){ed[++cnt]=(edge){head[x],y};head[x]=cnt;}
int dfn[5005], low[5005], dfnn;
int stack[5005], top, C[5005], scc;
bool ins[5005];
int pos[5005], D[5005];
void Tarjan(int x)
{
    dfn[x] = low[x] = ++dfnn;
    stack[++top] = x, ins[x] = 1;
    for (register int i = head[x] ; i ; i = ed[i].nxt)
    {
        int to = ed[i].to;
        if (!dfn[to]){Tarjan(to);low[x]=min(low[x],low[to]);}
        else if(ins[to]) low[x] = min(low[x], low[to]);
    }
    if (dfn[x] == low[x])
    {
        scc++;int y;
        do{
            y = stack[top--], ins[y] = 0;
            C[y] = scc;
        }while(y != x);
    }
}
inline void init()
{    
    cnt=1;top=0;dfnn=0;num=0;scc=0;
    memset(ins, 0, sizeof ins);
    memset(C, 0, sizeof C);
    memset(head, 0, sizeof head);
    memset(stack, 0, sizeof stack);
    memset(pos, 0, sizeof pos);
    memset(dfn, 0, sizeof dfn);
    memset(low, 0, sizeof low);
    memset(D, 0, sizeof D);
//    cleann(ins, 0), cleann(C, 0), cleann(head, 0), cleann(stack, 0);
//    cleann(pos, 0), cleann(dfn, 0), cleann(low, 0),cleann(D, 0);
}
int main()
{
    scanf("%d", &T);
    while (T--)
    {
        init();
        scanf("%d%d", &n, &m);
        for (register int i = 1 ; i <= m ; i ++) 
            scanf("%d%d", &L[i], &R[i]);
        for (register int i = 1 ; i <= n ; i ++)
            scanf("%d", &D[i]);
        if (m > 3 * n - 6) {puts("NO");continue;}
        for (register int i = 1 ; i <= n ; i ++)
            pos[D[i]] = i;
        for (register int i = 1 ; i <= m ; i ++)
        {
            R[i] = pos[R[i]], L[i] = pos[L[i]];
            if (R[i] < L[i]) swap(R[i], L[i]);//R[i] > L[i]
            if (R[i] - L[i] == 1 or (R[i] == n and L[i] == 1)) continue;
            L[++num] = L[i], R[num] = R[i];
        }
        for (register int i = 1 ; i <= num ; i ++)
        {
            for (register int j = 1 ; j <= num ; j ++)
            {
                if (i == j) continue;
                if ((L[i] > L[j] and R[j] > L[i] and R[j] < R[i]) or (L[i] < L[j] and R[j] > R[i] and R[i] > L[j]))
                {
                    add(i , j + num);
                    add(j + num, i);
                }
            }
        }
        for (register int i = 1 ; i <= 2 * num ; i ++) if (!dfn[i]) Tarjan(i);
        bool flag = 0;
        for (register int i = 1 ; i <= num ; i ++)
        {
            if (C[i] == C[i + num]) {puts("NO");flag = 1;break;}
        }
        
        if (!flag)puts("YES");
    }
}

 

 

 

 

posted @ 2018-07-07 23:05  zZhBr  阅读(105)  评论(0编辑  收藏  举报