• POJ 3207 Ikki's Story IV


    
    

    POJ 3207

    题意:平面上,一个圆,圆的边上按顺时针放着n个点。现在要连m条边,
    比如a,b,那么a到b可以从圆的内部连接,也可以从圆的外部连接。
    给你的信息中,每个点最多只会连接的一条边。问能不能连接这m条边,
    使这些边都不相交。
    
    思路:对于每条Link,要么在圆外,要么在圆内,且不可同时满足,
    只能两者取一,判断这M条Link是否合法,也就是M条Link不冲突,
    这就是典型的2-sat问题了。 将每条Link i 看做一个点,如果Link在圆内,
    则选做i ,如果在圆外, 则选做i'。对于两条线(i,j) ,如果i,j不能同时
    在圆内,也就可以推出两者不能同时在圆外,这个证明很容易,读者可
    以自行证明。i, j不能同时在圆内,则有边(i, j') 、(j ,i')、(i',j)、(j' ,i)
    (这是由2-sat的构图方式决定的,具体可以看《由对称性解2-SAT问题》
    这篇论文)。建图完了之后,本题就是判断2-sat问题是否有解,
    先求原图的强连通分量,并缩点,(这里我们称:(i,i')属于同一组),
    判断是否存在(i,i')属于同一组,若存在,则不可能,若不存在则可能。
    

    C++代码一

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <vector>
    #include <queue>
    #define MAXN 1005
    #define MAXM 2000005
    #define INF 1000000000
    using namespace std;
    int n, m, e, head[MAXN];
    int dfn[MAXN], low[MAXN], index, instack[MAXN], scc;
    int top, st[MAXN], fa[MAXN];
    int x[MAXN], y[MAXN];
    struct Edge
    {
        int v, next;
    }edge[MAXM];
    void init()
    {
        e = index = scc = top = 0;
        memset(dfn, 0, sizeof(dfn));
        memset(instack, 0, sizeof(instack));
        memset(head, -1, sizeof(head));
    }
    void insert(int x, int y)
    {
        edge[e].v = y;
        edge[e].next = head[x];
        head[x] = e++;
    }
    void tarjan(int u)
    {
        int v;
        instack[u] = 1;
        st[++top] = u;
        dfn[u] = low[u] = ++index;
        for(int i = head[u]; i != -1; i = edge[i].next)
        {
            v = edge[i].v;
            if(!dfn[v])
            {
                tarjan(v);
                low[u] = min(low[u], low[v]);
            }
            else if(instack[v]) low[u] = min(low[u], dfn[v]);
        }
        if(dfn[u] == low[u])
        {
            scc++;
            do
            {
                v = st[top--];
                instack[v] = 0;
                fa[v] = scc;
            }while(v != u);
        }
    }
    void build()
    {
        for(int i = 1; i <= m; i++)
        {
            scanf("%d%d", &x[i], &y[i]);
            x[i]++; y[i]++;
            if(x[i] > y[i]) swap(x[i], y[i]);
        }
        for(int i = 1; i <= m; i++)
            for(int j = i + 1; j <= m; j++)
                //通过判断得出 两条线的关系,如果通过判断只能一条在内一条在外,就连边
                if((x[i] <= x[j] && y[i] >= x[j] && y[i] <= y[j]) || (x[i] >= x[j] && x[i] <= y[j] && y[i] >= y[j]))
                {
                    insert(i, j + m);
                    insert(j, i + m);
                    insert(i + m, j);
                    insert(j + m, i);
                }
        n = 2 * m;
    }
    bool check()
    {
        for(int i = 1; i <= m; i++)
            if(fa[i] == fa[i + m]) return false;
        return true;
    }
    void solve()
    {
        for(int i = 1; i <= n; i++)
            if(!dfn[i]) tarjan(i);
        if(check()) printf("panda is telling the truth...
    ");
        else printf("the evil panda is lying again
    ");
    }
    int main()
    {
        scanf("%d%d", &n, &m);
        init();
        build();
        solve();
        return 0;
    }

    C++代码二

    点击

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    typedef double db;
    typedef long long ll;
    typedef unsigned long long ull;
    const int nmax = 1e5 + 7;
    const int INF = 0x3f3f3f3f;
    const ll LINF = 0x3f3f3f3f3f3f3f3f;
    const ull p = 67;
    const ull MOD = 1610612741;
    int n, m, cnt;
    typedef pair<int , int > pii;
    pii line[nmax];
    struct edge {
        int to, nxt;
    };
    struct graph {
        int tot, head[nmax];
        edge e[(int)1e6 + 7];
        void init() {
            tot = 0;
            memset(head, -1, sizeof head);
        }
        void add_edge(int u, int v) {
            e[tot].to = v;
            e[tot].nxt = head[u];
            head[u] = tot ++;
        }
    }g;
    inline bool checkcross(pii a, pii b) {
        if(a.first <= b.first && a.second >= b.first && a.second <= b.second)
            return true;
        else if(b.first <= a.first && b.second >= a.first && b.second <= a.second)
            return true;
        else if(a.first >= b.first && a.first <= b.second && a.second >= b.second)
            return true;
        else if(b.first >= a.first && b.first <= a.second && b.second >= a.second)
            return true;
        else
            return false;
    }
    int dfn[nmax], low[nmax], dfs_clock, color[nmax], scc;
    int ss[nmax], st;
    bool instack[nmax];
    void tarjan(int u, const graph & g) {
        dfn[u] = low[u] = ++dfs_clock;
        ss[st++] = u;
        instack[u] = true;
        for(int i = g.head[u]; i != -1; i = g.e[i].nxt) {
            int v = g.e[i].to;
            if(!dfn[v]) {
                tarjan(v, g);
                low[u] = min(low[u], low[v]);
            } else if (instack[v]) {
                low[u] = min(low[u], dfn[v]);
            }
        }
        if(dfn[u] == low[u]) {
            scc++;
            int tmp;
            while(true) {
                tmp = ss[--st];
                color[tmp] = scc;
                instack[tmp] = false;
                if(tmp == u)
                    break;
            }
        }
    }
    bool check() {
        for(int i = 1; i <= m; ++i) {
            if(color[i] == color[i+m])
                return false;
        }
        return true;
    }
    void init() {
        memset(dfn, 0, sizeof dfn);
        memset(low, 0, sizeof low);
        memset(color, 0, sizeof color);
    //    memset(instack, 0, sizeof instack);
        scc = dfs_clock = st;
        g.init();
    }
    int main(){
        while(scanf("%d %d", &n, &m) != EOF) {
            init();
            int a, b;
            for(int i = 1; i <= m; ++i) {
                scanf("%d %d", &a, &b);
                if(a < b) {
                    line[i].first = a;
                    line[i].second = b;
                } else {
                    line[i].first = b;
                    line[i].second = a;
                }
            }
    
            for(int i = 1; i <= m ;++i) {
                for(int j = i + 1; j <= m; ++j) {
                    if(checkcross(line[i], line[j])) {
                        g.add_edge(i, j + m);
                        g.add_edge(i + m, j);
                        g.add_edge(j, i + m);
                        g.add_edge(j + m, i);
                    }
                }
            }
            for(int i = 1; i <= 2 * m; ++i) {
                if(!dfn[i])
                    tarjan(i, g);
            }
            if(check()) {
                printf("panda is telling the truth...
    ");
            } else {
                printf("the evil panda is lying again
    ");
            }
        }
    
        return 0;
    }
  • 相关阅读:
    【iCore1S 双核心板_FPGA】例程十五:基于I2C的ARM与FPGA通信实验
    【iCore4 双核心板_ARM】例程二十一:LWIP_TCP_SERVER实验——以太网数据传输
    【iCore1S 双核心板_ARM】例程十五:USB_HID实验——双向数据传输
    【iCore4 双核心板_ARM】例程二十:LWIP_TCP_CLIENT实验——以太网数据传输
    【iCore1S 双核心板_FPGA】例程十四:FSMC总线通信实验——独立地址模式
    【iCore4 双核心板_FPGA】例程十五:基于单口RAM的ARM+FPGA数据存取实验
    【iCore4 双核心板_FPGA】例程十四:基于I2C的ARM与FPGA通信实验
    【iCore1S 双核心板_FPGA】例程十三:FSMC总线通信实验——复用地址模式
    【iCore4 双核心板_FPGA】例程十二:基于UART的ARM与FPGA通信实验
    【发布iCore3&iCore4ADM资料】
  • 原文地址:https://www.cnblogs.com/DWVictor/p/11347336.html
Copyright © 2020-2023  润新知