zoukankan      html  css  js  c++  java
  • POJ-3207-Ikki's Story IV Panda's Trick

    POJ 2-sat六题之一

    解题报告:http://blog.sina.com.cn/s/blog_64675f540100k13v.html

    题意:平面上,一个圆,圆的边上按顺时针放着n个点。现在要连m条边,比如a,b,那么a到b可以从圆的内部连接,也可以从圆的外部连接。给你的信息中,每个点最多只会连接的一条边。问能不能连接这m条边,使这些边都不相交。

    这题主要是了解把边看成是2-sat的变量。边的里边和外边对应变量的true和false;

    解题报告:

    题意可能刚开始不是很好理解,比如1 5连边,2,6连边,由于点是顺序排列的,一画图就可以发现,这两条边必须一个从圆外面连,一个从内部连,否则就会相交。如果再加入3 7这条边,那么就必须相交了。

    这样,就可以转化成标准的2-sta问题:

    1:每个边看成2个点:分别表示在内部连接和在外部连接,只能选择一个。计作点i和点i'

    2:如果两条边i和j必须一个画在内部,一个画在外部(一个简单判断就可以)

    那么连边:

    i->j’, 表示i画内部的话,j只能画外部,即j’

    j->i’,同理

    i’->j,同理

    j’->i,同理

    View Code
    // File Name: 3207.cpp
    // Author: zlbing
    // Created Time: 2013/1/22 18:45:07
    
    #include<iostream>
    #include<string>
    #include<algorithm>
    #include<cstdlib>
    #include<cstdio>
    #include<set>
    #include<map>
    #include<vector>
    #include<cstring>
    #include <stack>
    using namespace std;
    #define MAXN 1020
    struct TwoSAT{
        int n;
        vector<int>G[MAXN*2];
        bool mark[MAXN*2];
        stack<int>S;
        bool dfs(int x)
        {
            if(mark[x^1])return false;
            if(mark[x])return true;
            mark[x]=true;
            S.push(x);
            for(int i=0;i<G[x].size();i++)
            {
                int v=G[x][i];
                if(!dfs(v))return false;
            }
            return true;
        }
        void init(int _n)
        {
            n=_n;
            for(int i=0;i<2*n;i++)
                G[i].clear();
            memset(mark,0,sizeof(mark));
        }
    /*    void add_clause(int x,int xval,int y,int yval)
        {
            x=x*2+xval;
            y=y*2+yval;
            G[x^1].push_back(y);
            G[y^1].push_back(x);
        }
    */
        void add_clause(int x,int y)
        {
            x=2*x;
            y=2*y;
            G[x].push_back(y+1);
            G[x+1].push_back(y);
            G[y].push_back(x+1);
            G[y+1].push_back(x);
        }
        bool solve()
        {
            for(int i=0;i<2*n;i=i+2)
            {
                if(!mark[i]&&!mark[i+1]){
                      while(!S.empty())
                      {
                          S.pop();
                      }
                    if(!dfs(i))
                    {
                        while(!S.empty())
                        {
                            mark[S.top()]=false;
                            S.pop();
                        }
                        if(!dfs(i+1))return false;
                    }
                }
            }
            
    //        for(int i=0;i<2*n;i++)
    //            if(mark[i])printf("%d ",T[i/2][i%2]);
    //        printf("\n");
            return true;
        }
    };
    
    int T[MAXN][2];
    int main(){
        int n,m;
        while(~scanf("%d%d",&n,&m))
        {
            for(int i=0;i<m;i++)
            {
                scanf("%d%d",&T[i][0],&T[i][1]);
                if(T[i][0]>T[i][1])swap(T[i][0],T[i][1]);
            }
            TwoSAT solver;
            solver.init(m);
            for(int i=0;i<2*m;i+=2)
                for(int j=i+2;j<2*m;j+=2)
                {
                    if(T[i/2][0]>T[j/2][0]&&T[i/2][0]<T[j/2][1]&&T[i/2][1]>T[j/2][1]||T[j/2][0]>T[i/2][0]&&T[j/2][0]<T[i/2][1]&&T[j/2][1]>T[i/2][1])
                        solver.add_clause(i,j);
                }
            if(solver.solve())
                printf("panda is telling the truth...\n");
            else 
                printf("the evil panda is lying again\n");
            
        }
        return 0;
    }
  • 相关阅读:
    一周学C#第五天——命名空间
    一周学C#之第4天——语句
    一周学C#之第一天——基础知识
    数据库ADONET使用强类型DataSet
    .NET中的主要类型简表
    一周学C#第六天——枚举
    一周学C#之第二天(函数)
    一周学C#之第三天——值的类型
    数据库ADONET向数据库提交更新
    一个低级错误导致的StackOverflowException异常
  • 原文地址:https://www.cnblogs.com/arbitrary/p/2872242.html
Copyright © 2011-2022 走看看