poj 3207 Ikki's Story IV - Panda's Trick(2-sat)

来源:互联网 发布:改本地host变更域名 编辑:程序博客网 时间:2024/06/05 00:45

题目链接:

点击打开链接

题目大意:

给出一个圆,圆上有一些点,他们之间存在一些边,既可以通过园内相连,也可以通过圆外相连,这些线不相交,问这种情况存在吗?

题目分析:

一条线既可以放在圆外,也可以放在圆内,那么就是2-sat的两种状态,如果某两条边的交叉,也就是某条边的左端点在另一条边的左右端点之间的时候,那么这两条线段就必须放在圆的不同侧,所以就要有关系:假设这两条直线为l1,l2,那么l1在圆内,l1一定在圆外,l2在圆外,l1一定在圆内,l2在圆内,那么l1一定在圆外,l2在圆外,那么l1一定在圆内。然后利用2-sat判断是否有解即可

代码如下:

#include <iostream>#include <cstring>#include <cstdio>#include <algorithm>#include <vector>#include <stack>#define MAX 1007using namespace std;typedef pair<int,int> PII;int mark[MAX],dfn[MAX],low[MAX],belong[MAX],times,cnt;vector<int> e[MAX];stack<int> s;PII p[MAX];void tarjan ( int u ){    dfn[u] = low[u] = ++times;    mark[u] = 1;    s.push ( u );    int len = e[u].size();    for ( int i = 0 ; i < len ; i++ )    {        int v = e[u][i];        if ( !mark[v] )        {            tarjan ( v );            low[u] = min ( low[u] , low[v] );        }        if ( mark[v] == 1 )            low[u] = min ( low[u] , dfn[v] );    }    if ( dfn[u] == low[u] )    {        int temp;        do        {            temp = s.top();            belong[temp] = cnt;            mark[temp] = 2;            s.pop();        }while ( temp != u );        cnt++;    }}void init ( ){    memset ( mark , 0 , sizeof ( mark ));    for ( int i = 0 ; i < MAX ; i++ )        e[i].clear();    while ( !s.empty()) s.pop();    times = cnt = 0;}int n,m;int main ( ){    int u,v;    while ( ~scanf ( "%d%d" , &n , &m ) )    {        init ( );        for ( int i = 0 ; i < m ; i++ )        {            scanf ( "%d%d" , &p[i].first , &p[i].second );            if ( p[i].first > p[i].second )                swap ( p[i].first , p[i].second );        }        sort ( p , p+m );        for ( int i = 0 ; i < m ; i++ )            for ( int j = i+1 ; j < m ; j++ )            {                if ( p[i].first < p[j].first &&                     p[j].second > p[i].second &&                     p[i].second > p[j].first )                {                    e[i*2].push_back ( j*2+1 );                    e[j*2].push_back ( i*2+1 );                    e[i*2+1].push_back ( j*2 );                    e[j*2+1].push_back ( i*2 );                }            }        for ( int i = 0 ; i < 2*m ; i++ )            if ( !mark[i] ) tarjan ( i );        bool flag = true;        for ( int i = 0 ; i < m ; i++ )            if ( belong[i<<1] == belong[i<<1|1] )                flag = false;        if ( flag )            puts ( "panda is telling the truth...");        else puts ("the evil panda is lying again");    }}


0 0