zoukankan      html  css  js  c++  java
  • pku 3207

    这道题感觉最难的是想到他是一个2-sat,即使我是按2-sat题目去找的……

    想了很久,还是觉得像贪心,但是贪心之后就不太好做了,以下是参考别人的代码写的,

    翻了好多代码,都不太理解,最后感觉这个感觉比较好理解吧,,但忘了是谁的blog里面的了

    先不写明出处了先

    /*
    题意是:在一个有0,1,2,。。。n-1 个点组成的圆中,只能从圆里面和外面画线,
    问你能否将m条边连起来,并且不能相交。

    我的想法是:对于每条边要么从圆里面走,要么从圆外面走。那么,我们这样定义i
    表示从里面走,i+n表示从外面走。然后我们遍历所有的两两边,如果他们交错了,
    那么他们之间就有这样的关系:i从里面走,那么j就得走外面,i从外面走,那么j就
    得走里面,反之亦然,即:
    i->j+n i+n->j j->i+n j+n->i
    理解:把点当边,把边当点
    2011-7-13
    */

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <vector>
    #define nMax 1005
    #define mMax 505
    using namespace std;
    int dfn[nMax], low[nMax], stack[nMax], belong[nMax],a[mMax], b[mMax];
    int top, cnt, n, m, ans;
    bool instack[nMax];
    vector<int> tree[nMax];

    void init()
    {
    for(int i=0; i<n*2; i++)
    {
    tree[i].clear();
    }
    }

    void BuildGraph()
    {
    for(int i=0; i<m; i++)
    {
    scanf("%d%d", &a[i], &b[i]);
    if(a[i]>b[i]) swap(a[i], b[i]);
    }
    for(int i=0; i<m; i++)
    {
    for(int j=i+1; j<m; j++)
    {
    if((a[i]<a[j] && b[i]<b[j] && a[j]<b[i]) || (a[i]>a[j] && b[i]>b[j] && a[i]<b[j]))
    {
    tree[2*i].push_back(2*j+1);
    tree[2*j+1].push_back(2*i);
    tree[2*j].push_back(2*i+1);
    tree[2*i+1].push_back(2*j);
    }
    }
    }
    }

    void dfs(int i)
    {
    int j;
    dfn[i]=low[i]=++ans;
    instack[i]=true;
    stack[++top]=i;
    for(int k=0; k<tree[i].size(); k++)
    {
    j=tree[i][k];
    if(!dfn[j])
    {
    dfs(j);
    if(low[j]<low[i])
    low[i]=low[j];
    }
    else if(instack[j] && dfn[j]<low[i])
    low[i]=dfn[j];
    }
    if(dfn[i]==low[i])
    {
    cnt++;
    do
    {
    j=stack[top--];
    instack[j]=0;
    belong[j]=cnt;
    }while(j!=i);
    }
    }
    void Tarjan()
    {
    top=cnt=ans=0;
    memset(dfn, 0, sizeof(dfn));
    for(int i=0; i<2*m; i++)
    if(!dfn[i])
    dfs(i);
    }

    bool Judge()
    {
    for(int i=0; i<2*m; i+=2)
    if(belong[i]==belong[i+1])
    return 0;
    return 1;
    }

    int main()
    {
    scanf("%d%d", &n, &m);
    init();
    BuildGraph();
    Tarjan();
    if(Judge()) puts("panda is telling the truth...");
    else puts("the evil panda is lying again");
    return 0;
    }
    作者:FreeAquar
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
  • 相关阅读:
    Vue练习三十六:05_01_模拟select控件
    Vue练习三十五:04_09_星级评分系统
    Vue练习三十四:04_07_各种数组方法练习
    Vue练习三十三:04_06_当前输入框高亮显示
    Vue练习三十二:04_05_设置读取属性
    【CC++笔记】指针输出字符串
    【CC++笔记】数组指针越界
    【算法】递归思想
    【学习方法】堕落大学生补救方法
    【数字逻辑】补码技巧
  • 原文地址:https://www.cnblogs.com/FreeAquar/p/2104956.html
Copyright © 2011-2022 走看看