POJ 3207 Ikki's Story IV Panda's Trick

POJ_3207

这是一个2-SAT的问题,首先我们要找到核心的变量,我们可以观察到,只有连成的线具有要么在内、要么在外的这样的逻辑关系,因此我们可以把连成的线当做核心变量。

接下来我们需要做的就是去分析,什么情况时两条线才会产生相互制约的关系。为了方便描述,我们不妨把两条线分别记作<i1,i2>(i1<i2)<j1,j2>(j1<j2)。不难发现,当出现j1>i1&&j1<i2&&j2>i2或者i1>j1&&i1<i2&&i2>j2的情况时,两条线会相互制约,即如果i在内,j必须在外,如果j在内,i必须在外,反过来也是一样的。因此对于这种情况我们需要连四条边i->~j~i->jj->~i~j->i

#include<stdio.h>
#include<string.h>
#define MAXN 1010
#define MAXM 600010
int first[MAXN], next[MAXM], v[MAXM], n, m, e;
int dfn[MAXN], low[MAXN], cnt, s[MAXN], ins[MAXN], top;
int color[MAXN], col, link1[MAXM], link2[MAXM];
void add_edge(int i, int j)
{
v[e] = j;
next[e] = first[i];
first[i] = e;
e ++;
}
void init()
{
int i, j, k;
e = 0;
memset(first, -1, sizeof(first));
for(i = 0; i < m; i ++)
{
scanf("%d%d", &link1[i], &link2[i]);
if(link1[i] > link2[i])
{
k = link1[i];
link1[i] = link2[i];
link2[i] = k;
}
}
for(i = 0; i < m; i ++)
for(j = i + 1; j < m; j ++)
{
if(link1[j] < link2[i] && link1[j] > link1[i] && link2[j] > link2[i])
{
add_edge(2 * i, 2 * j + 1);
add_edge(2 * i + 1, 2 * j);
add_edge(2 * j, 2 * i + 1);
add_edge(2 * j + 1, 2 * i);
}
else if(link1[i] < link2[j] && link1[i] > link1[j] && link2[i] > link2[j])
{
add_edge(2 * i, 2 * j + 1);
add_edge(2 * i + 1, 2 * j);
add_edge(2 * j, 2 * i + 1);
add_edge(2 * j + 1, 2 * i);
}
}
}
void tarjan(int u)
{
int i;
dfn[u] = low[u] = ++ cnt;
for(i = first[u]; i != -1 ; i = next[i])
{
if(!dfn[v[i]])
{
s[top ++] = v[i];
ins[v[i]] = 1;
tarjan(v[i]);
if(low[v[i]] < low[u])
low[u] = low[v[i]];
}
else if(ins[v[i]] && dfn[v[i]] < low[u])
low[u] = dfn[v[i]];
}
if(dfn[u] == low[u])
{
for(s[top] = -1; s[top] != u;)
{
top --;
ins[s[top]] = 0;
color[s[top]] = col;
}
col ++;
}
}
int com()
{
int i;
cnt = top = col =0;
memset(dfn, 0, sizeof(dfn));
memset(ins, 0, sizeof(ins));
for(i = 0; i < 2 * m; i ++)
if(!dfn[i])
{
s[top ++] = i;
ins[i] = 1;
tarjan(i);
}
for(i = 0; i < 2 * m; i ++)
if(color[i] == color[i ^ 1])
return 0;
return 1;
}
int main()
{
while(scanf("%d%d", &n, &m) ==2)
{
init();
if(com())
printf("panda is telling the truth...\n");
else
printf("the evil panda is lying again\n");
}
return 0;
}


原文地址:https://www.cnblogs.com/staginner/p/2198651.html