您的位置:首页 > 其它

poj 3207 2-sat

2015-08-21 15:03 351 查看
思路:把每一条线段当做点,则有“内”、“外”两种取值,然后在冲突的线段之间连边,判断是否有解即可。

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;

const int N = 500;
const int M = 1000000;
int head[N * 2];
int s[N * 2];
bool mark[N * 2];
int n, e, c;

struct Edge
{
int v, next;
} edge[M];

void addEdge( int u, int v )
{
edge[e].v = v;
edge[e].next = head[u];
head[u] = e++;
}

void init()
{
e = 0;
memset( head, -1, sizeof(head) );
memset( mark, false, sizeof(mark) );
}

bool dfs( int u )
{
if ( mark[u ^ 1] ) return false;
if ( mark[u] ) return true;
mark[u] = true;
s[c++] = u;
for ( int i = head[u]; i != -1; i = edge[i].next )
{
int v = edge[i].v;
if ( !dfs(v) ) return false;
}
return true;
}

bool solve()
{
for ( int i = 0; i < 2 * n; i += 2 )
{
if ( !mark[i] && !mark[i + 1] )
{
c = 0;
if ( !dfs(i) )
{
while ( c )
{
c--;
mark[s[c]] = false;
}
if ( !dfs( i + 1 ) ) return false;
}
}
}
return true;
}

struct T
{
int x, y;
} t
;

int main ()
{
scanf("%d%d", &n, &n);
init();
for ( int i = 0; i < n; i++ )
{
scanf("%d%d", &t[i].x, &t[i].y);
if ( t[i].x > t[i].y ) swap( t[i].x, t[i].y );
for ( int j = 0; j < i; j++ )
{
if ( ( t[i].x < t[j].x && t[i].y < t[j].y && t[i].y > t[j].x )
|| ( t[i].x > t[j].x && t[i].y > t[j].y && t[i].x < t[j].y ) )
{
int li = i << 1, ri = li | 1;
int lj = j << 1, rj = lj | 1;
addEdge( li, rj );
addEdge( ri, lj );
addEdge( lj, ri );
addEdge( rj, li );
}
}
}
if ( solve() )
{
puts("panda is telling the truth...");
}
else
{
puts("the evil panda is lying again");
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: