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

    题意

    Here

    思考

    如果单独的平面图判定肯定是很麻烦的,但题目给了一个条件,此平面图存在哈密顿回路,我们将哈密顿回路画成一个圆,那么原图的边(除去哈密顿回路上的边)可以看作是该圆的弦,考虑圆中两条相交的弦 ((u_1, v_1),(u_2, v_2)(u_1,v_1),(u_2,v_2)) ,由于是平面图,我们可以将其中的一条翻到圆外去(但两条弦不能同时翻到圆外去,原因是如果他们在圆内相交,那么在圆外也会相交,可以画图模拟一下),我们考虑将弦视为点,把相交的弦连边,这样,平面图的判定就转为了新图的二分图判定~

    要注意的一点:按照题中所给的m的范围是过不去的,但这其实是个假数据范围,平面图有一条性质是 (m leq 3n-6),有兴趣的同学可以去了解一下证明

    代码

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    int read(){
        int x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return x * f;
    }
    const int M = 10010;
    struct node{
        int nxt, to;
    }edge[700 * 700 * 2];
    int head[M], num, col[M];
    void build(int from, int to){
        edge[++num].nxt = head[from];
        edge[num].to = to;
        head[from] = num;
    }
    bool dfs(int u, int color){
        col[u] = color;
        for(int i=head[u]; i; i=edge[i].nxt){
            int v = edge[i].to;
            if(col[v] == color) return 0;
            if(col[v] == 0 && !dfs(v, -color)) return 0;
        }
        return 1;
    }
    bool check(int u1, int v1, int u2, int v2){
        return (u1 < u2 && u2 < v1 && v1 < v2) || (u2 < u1 && u1 < v2 && v2 < v1);
    }
    int t, n, m;
    int from[M], to[M], G[M];
    void clearx(){
        memset(head, 0, sizeof(head)); num = 0;
        memset(col, 0, sizeof(col));
        memset(G, 0, sizeof(G));
    }
    int main(){
        t = read();
        while(t --){
            n = read(), m = read(); int flag = 0;
            clearx();
            for(int i=1; i<=m; i++){
                from[i] = read(); to[i] = read();
            }
            for(int i=1; i<=n; i++) G[read()] = i;
            if(m > 3 * n - 6){
                puts("NO"); continue;
            }
            for(int i=1; i<=m-1; i++){
                for(int j=i+1; j<=m; j++){
                    int u1 = G[from[i]], v1 = G[to[i]], u2 = G[from[j]], v2 = G[to[j]];
                    if(u1 > v1) swap(u1, v1); if(u2 > v2) swap(u2, v2);
                    if( check(u1, v1, u2, v2) ) build(i, j), build(j, i);
                }
            }
            for(int i=1; i<=m; i++){
                if(col[i] == 0){
                    if(!dfs(i, 1)){
                        flag = 1;
                        break;
                    }
                }
            }
            if(!flag) puts("YES");
            else puts("NO");
        }
        return 0;
    }
    

    总结

    题目要分析清楚,某些题目可能会有坑(比如这题m的虚假范围)。有时候能把题目转换成较简单的问题(将本题平面图判定转为了二分图判定)。本题还有其他解法:并查集/2-SAT

  • 相关阅读:
    找最大质因子问题
    ACM基础训练题解4302 丢失的牛
    ACM基础训练题解4301 城市地平线
    hnu 7/19 A Broken Audio Signal
    hnu7/20比赛 BUG 题解
    http://acm.hnu.cn/online/?action=problem&type=show&id=12817&courseid=267 7.19hnu/数据结构/数学 xxs.code
    SGU 解题报告
    2015 Multi-University Training Contest 1 题解&&总结
    HDU 5351 MZL's Border (规律,大数)
    SGU 239.Minesweeper
  • 原文地址:https://www.cnblogs.com/alecli/p/9898048.html
Copyright © 2011-2022 走看看