POJ 3207 Ikki's Story IV - Panda's Trick【2-SAT】

题意:已知一个圆上顺时针放着 n 个点,这 n 个点中有m对顶点之间有连线,连线要么在园外要么在圆内,每个点最多连接一条边,问是否存在一种连接情况满足所有的

        边都不相交。

分析:将每条边看成两个点 i ,i+m 分别表示边在内部和在外部,

        如果两条边i,j的端点存在序号上的交叉,则这两对点之间的连线一个在外部一个在内部

        即如果存在 i,则必存在 j+m ,如果存在 j ,则必存在 i+m,

           如果存在 i+m,则必存在 j ,如果存在 j+m ,则必存在 i,

       建图的时候连的边为

       i -> j+m

       j -> i+m

      i+m -> j

      j+m -> i

     求出强连通分量并染色,判断是否存在冲突的情况即可。

#include<stdio.h>
#include<string.h>
#define maxn 1100
#define clr(x)memset(x,0,sizeof(x))
#define min(a,b)(a)<(b)?(a):(b)
#define max(a,b)(a)>(b)?(a):(b)
struct Edg
{
    int u,v;
}e[1100];
struct node
{
    int to,next;
}edge[1000000];
int tot;
int head[maxn];
void add(int s,int t)
{
    edge[tot].to=t;
    edge[tot].next=head[s];
    head[s]=tot++;
}
int dfn[maxn];
int low[maxn];
int sta[maxn];
int ins[maxn];
int col[maxn];
int top,sn,ti;
void tarjan(int u)
{
    dfn[u]=low[u]=++ti;
    sta[++top]=u;
    ins[u]=1;
    int i,k;
    for(i=head[u];i;i=edge[i].next)
    {
        k=edge[i].to;
        if(dfn[k]==0)
        {
            tarjan(k);
            low[u]=min(low[u],low[k]);
        }
        else if(ins[k])
            low[u]=min(low[u],dfn[k]);
    }
    if(dfn[u]==low[u])
    {
        sn++;
        do
        {
            k=sta[top--];
            ins[k]=0;
            col[k]=sn;
        }while(k!=u);
    }
}
int main()
{
    int n,m,i,j;
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        for(i=0;i<m;i++)
        {
            scanf("%d%d",&e[i].u,&e[i].v);
            if(e[i].u>e[i].v)
            {
                int tmp=e[i].u;
                    e[i].u=e[i].v;
                    e[i].v=tmp;
            }
        }
        tot=1;
        clr(head);
        for(i=0;i<m;i++)
            for(j=i+1;j<m;j++)
                if(e[i].u<e[j].v&&e[i].u>e[j].u&&e[i].v>e[j].v
                 ||e[i].v>e[j].u&&e[i].v<e[j].v&&e[i].u<e[j].u)
                {
                    add(i,j+m);
                    add(j,i+m);
                    add(j+m,i);
                    add(i+m,j);
                }
        sn=top=ti=0;
        clr(dfn); clr(low);
        clr(ins); clr(col);
        for(i=0;i<2*m;i++)
            if(dfn[i]==0)
                tarjan(i);
        for(i=0;i<m;i++)
            if(col[i]==col[i+m])
                break;
        if(i==m)
            printf("panda is telling the truth...\n");
        else 
            printf("the evil panda is lying again\n");
    }
    return 0;
}

 

posted @ 2012-09-29 14:06  'wind  阅读(176)  评论(0编辑  收藏  举报