zoukankan      html  css  js  c++  java
  • HNOI2010 平面图判定

    感觉 (2-SAT) 的题目跟网络流有点点像,都是考虑怎么建图,然后跑板子

    (2-SAT) 的题目的一个建图的思路就是转换成一真一假的格式,然后就比较好

    Description

    给一张图和一条图上的哈密尔顿回路,判定是不是可以把它转换成一个平面图

    (n leq 200),(m leq 10000)

    多组数据((doc)我多测没清空,(WA)了好几发)

    Solution

    先是一个实用 (trick) :平面图中,(m leq 3n-6)

    证明等学平面图的时候再说吧

    把这一个哈密尔顿回路想成平面上的一个圆(多边形)

    而非回路上的点就是圆上的弦(多边形对角线),或者连在环外部

    两条弦相交的条件还得满足

    for (int i = 1; i < m; ++i) {
            for (int j = i + 1; j <= m; ++j) {
                int p = id[ex[i]], q = id[ey[i]], r = id[ex[j]], s = id[ey[j]];
                if (p > q)
                    swap(p, q);
                if (r > s)
                    swap(r, s);
                if ((p < r && q > r && q < s || (r < p && s > p && s < q)))
                    add(i, j + m), add(i + m, j), add(j, i + m), add(j + m, i);
            }
        }
    

    反正博主是懂了(画图就可以感性理解)

    然后跑 (tarjan) 就没了

    Code

    #include <bits/stdc++.h>
    using namespace std;
    #define int long long
    namespace yspm {
    inline int read() {
        int res = 0, f = 1;
        char k;
        while (!isdigit(k = getchar()))
            if (k == '-')
                f = -1;
        while (isdigit(k)) res = res * 10 + k - '0', k = getchar();
        return res * f;
    }
    const int N = 1e4 + 10;
    int dfn[N], low[N], scc[N], st[N], tot, tim, top, u[N], v[N], c[N], ex[N], ey[N], now;
    vector<int> g[N];
    int n, id[N], m;
    bool f[300][300], vis[N];
    inline void add(int u, int v) { return g[u].push_back(v), void(); }
    inline void tarjan(int x) {
        dfn[x] = low[x] = ++tim;
        vis[x] = 1;
        st[++top] = x;
        int sz = g[x].size();
        for (int i = 0; i < sz; ++i) {
            int t = g[x][i];
            if (!dfn[t])
                tarjan(t), low[x] = min(low[x], low[t]);
            else if (vis[t])
                low[x] = min(low[x], dfn[t]);
        }
        if (dfn[x] == low[x]) {
            ++tot;
            while (st[top] != x) scc[st[top]] = tot, vis[st[top--]] = 0;
            scc[st[top]] = tot, vis[st[top--]] = 0;
        }
        return;
    }
    #define cl(x) memset(x, 0, sizeof(x))
    inline void prework() {
        cl(dfn);
        cl(scc);
        cl(st);
        cl(u);
        cl(v);
        cl(ex);
        now = 0;
        tim = 0;
        tot = 0;
        top = 0;
        cl(ey);
        cl(id);
        cl(vis);
        cl(f);
        for (int i = 1; i < N; ++i) g[i].clear();
        return;
    }
    inline void work() {
        n = read();
        m = read();
        for (int i = 1; i <= m; ++i) {
            u[i] = read();
            v[i] = read();
            if (u[i] > v[i])
                swap(u[i], v[i]);
        }
        for (int i = 1, x, y; i <= n; ++i) {
            c[i] = read();
            id[c[i]] = i;
            if (i > 1) {
                x = c[i];
                y = c[i - 1];
                f[min(x, y)][max(x, y)] = 1;
            }
        }
        if (m > 3 * n - 6)
            return puts("NO"), void();
        f[min(c[1], c[n])][max(c[1], c[n])] = 1;
        for (int i = 1; i <= m; ++i) {
            if (f[u[i]][v[i]])
                continue;
            ex[++now] = u[i], ey[now] = v[i];
        }
        //把非回路上的点找出来
        m = now;
        for (int i = 1; i < m; ++i) {
            for (int j = i + 1; j <= m; ++j) {
                int p = id[ex[i]], q = id[ey[i]], r = id[ex[j]], s = id[ey[j]];
                if (p > q)
                    swap(p, q);
                if (r > s)
                    swap(r, s);
                if ((p < r && q > r && q < s || (r < p && s > p && s < q)))
                    add(i, j + m), add(i + m, j), add(j, i + m), add(j + m, i);
            }
        }
        for (int i = 1; i <= m * 2; ++i)
            if (!dfn[i])
                tarjan(i);
        for (int i = 1; i <= m; ++i)
            if (scc[i] == scc[i + m])
                return puts("NO"), void();
        puts("YES");
        return;
    }
    signed main() {
        int T = read();
        while (T--) prework(), work();
        return 0;
    }
    }  // namespace yspm
    signed main() { return yspm::main(); }
    
  • 相关阅读:
    在Idea中使用Eclipse编译器
    Idea切换svn分支,类似Eclipse的Switch功能
    Spring AOP详解
    CGLib动态代理原理及实现
    IDEA下搜狗输入法输入中文时卡着不动的参考解决方法
    Nginx反向代理丢失cookie的问题
    redis连接池自动释放
    Redis常用命令
    waitpid之status意义解析
    bash中管道命令返回值如何确定(下)
  • 原文地址:https://www.cnblogs.com/yspm/p/12324678.html
Copyright © 2011-2022 走看看