• 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;
    }


  • 相关阅读:
    记录ICallbackEventHandler 同时并发访问容易引发的问题
    IIS 属性
    Solaris10 安装
    VerifyRenderingInServerForm和EnableEventValidation引发的两个问题
    Solaris 上网配置
    动态数据类型转换
    RDLC 折线图
    codesmith复制中文乱码解决
    关于手机等品牌型号搜索与采集的中文分词分离
    说点包租公限制共享上网的破事
  • 原文地址:https://www.cnblogs.com/staginner/p/2198651.html
Copyright © 2020-2023  润新知