POJ 3207 Ikki's Story IV - Panda's Trick (2-SAT)

               Ikki's Story IV - Panda's Trick
Time Limit: 1000MS   Memory Limit: 131072K
Total Submissions: 11405   Accepted: 4168

Description

liympanda, one of Ikki’s friend, likes playing games with Ikki. Today after minesweeping with Ikki and winning so many times, he is tired of such easy games and wants to play another game with Ikki.

liympanda has a magic circle and he puts it on a plane, there are n points on its boundary in circular border: 0, 1, 2, …, n − 1. Evil panda claims that he is connecting m pairs of points. To connect two points, liympanda either places the link entirely inside the circle or entirely outside the circle. Now liympanda tells Ikki no two links touch inside/outside the circle, except on the boundary. He wants Ikki to figure out whether this is possible…

Despaired at the minesweeping game just played, Ikki is totally at a loss, so he decides to write a program to help him.

Input

The input contains exactly one test case.

In the test case there will be a line consisting of of two integers: n and m (n ≤ 1,000, m ≤ 500). The following m lines each contain two integers ai and bi, which denote the endpoints of the ith wire. Every point will have at most one link.

Output

Output a line, either “panda is telling the truth...” or “the evil panda is lying again”.

Sample Input

4 2
0 1
3 2

Sample Output

panda is telling the truth...
思路:
又因为Tarjan,WA了一发。。。
由于2-SAT有了很多牛逼的博客,所以我只说这一题要怎么搞。
先判断两个link会不会相交,如果会的话,就要开始连线了,注意新建的图,节点是原图的link,假设我们找到的两条边,一条是i,一条是j,那么,以i点,表示link【i】在圆内以i+m点表示在圆外。j同理。连接的表示,如果选了起点,那么一定要选终点。又因为如果i在圆内,那么j一定不再圆内,所以,一共要连四条边,分别是,i->j+m,j->i+m以及他们的反向边。
此后,用Tarjan缩点,如果i与i+m在同一个联通分量之内,那么邪恶熊猫一定撒谎了。
如果不再的话,那么邪恶熊猫一定没有撒谎,原因在于,如果邪恶熊猫如果说谎,那么一定存在,i和j在一个联通分量内,那我们建图的时候,又建立了j->i+m这样一条边,所以,i和i+m在说谎时一定在一个区域内,如果不在那么就一定没有i与j在同一联通区间内,于是他就没有说谎。
代码:
#include<iostream>
#include<vector>
#include<cstdio>
#include<algorithm>
#include<stack>
using namespace std;
int n,m,sig;
int dfn[100086],low[100086];
bool book[100086];
int color[100086],index;
struct node
{
    int x;
    int y;
}link[100024];
vector<int>u[100024];
stack<int>st;
void init()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++){
        scanf("%d%d",&link[i].x,&link[i].y);
        if(link[i].x>link[i].y){swap(link[i].x,link[i].y);}
    }
}

bool jud(int a,int b,int c,int d)
{
    if(a<c&&c<b&&b<d){
        return true;
    }
    if(c<a&&a<d&&d<b){
        return true;
    }
    return false;
}

void build()
{
    for(int i=1;i<=m;i++){
        for(int j=i+1;j<=m;j++){
            if(jud(link[i].x,link[i].y,link[j].x,link[j].y)){
                u[i].push_back(j+m);
                u[j].push_back(i+m);
                u[j+m].push_back(i);
                u[i+m].push_back(j);
            }
        }
    }
}

void tarjan(int t)
{
    dfn[t]=low[t]=++index;
    st.push(t);
    book[t]=true;
    int siz=u[t].size();
    for(int i=0;i<siz;i++){
        if(!dfn[u[t][i]]){
            tarjan(u[t][i]);
            low[t]=min(low[t],low[u[t][i]]);
        }
        else if(book[u[t][i]]){
            low[t]=min(low[t],low[u[t][i]]);
        }
    }

    int pos;
    if(dfn[t]==low[t]){
        sig++;
        while(true){
            if(st.empty()){break;}
            pos=st.top();
            st.pop();
            color[pos]=sig;
            book[pos]=0;
            if(pos==t){break;}
        }
    }
}

void solve()
{
    for(int i=0;i<n;i++){
        if(!dfn[i]){
            tarjan(i);
        }
    }

    for(int i=1;i<=m;i++){
        if(color[i]==color[i+m]&&color[i]!=0){
            printf("the evil panda is lying again\n");return;
        }
    }
    printf("panda is telling the truth...\n");
}

int main()
{
    init();
    build();
    solve();
}

  

posted @ 2018-08-01 10:46  断腿三郎  阅读(244)  评论(0编辑  收藏  举报