[BZOJ1997][Hnoi2010]Planar && 并查集

来源:互联网 发布:mac版office365密钥 编辑:程序博客网 时间:2024/05/07 06:01

记集合m+i 为不能和第i条边在同一集合的边 弱i,j相交 且i,j在同一组合 则不合法

#include<cstdio>#include<algorithm>#include<cstring>#include<iostream>#include<queue>#include<deque>#define SF scanf#define PF printfusing namespace std;typedef long long LL;const int MAXN = 200;const int MAXM = 10000;int fa[MAXN*2+10], n, m, X[MAXM+10], Y[MAXM+10], rk[MAXN+10];int M, G[MAXN+10][MAXN+10], c[MAXN+10], x[MAXM+10], y[MAXM+10];int find(int x) {    if(x == fa[x]) return x;    return fa[x] = find(fa[x]);}inline bool crs(int x1, int y1, int x2, int y2)     // 判断是否相交{    if (x1 == x2 || x1 == y2 || y1 == x2 || y1 == y2) return false;    x1 = rk[x1];    y1 = rk[y1];    x2 = rk[x2];    y2 = rk[y2];    if (x1 > y1) swap(x1, y1);    return (bool)(x1 < x2 && x2 < y1) != (bool)(x1 < y2 && y2 < y1);}void check(int m) {    for(int i = 1; i <= m*2; i++) fa[i] = i;    for(int i = 1; i <= m; i++)        for(int j = 1; j <= m; j++)             if(crs(x[i], y[i], x[j], y[j])) {                int fa1 = find(i), fa2 = find(j);                if(fa1 == fa2) {                    puts("NO"); return ;                }                fa[fa1] = find(m+j);                fa[fa2] = find(m+i);            }    puts("YES");}int main() {    int kase = 0;    int _T; SF("%d", &_T); while(_T--) {        kase++;        int tot = 0;        SF("%d%d", &n, &m);        for(int i = 1; i <= m; i++) SF("%d%d", &X[i], &Y[i]);        for(int i = 1; i <= n; i++) {            SF("%d", &c[i]);            rk[c[i]] = i;            G[c[i]][c[i-1]] = kase;        }        if(m > 3*n-6) {            puts("NO");            continue;         }        for(int i = 1; i <= m; i++) {            if(G[X[i]][Y[i]] != kase) {                tot++;                x[i] = X[i];                y[i] = Y[i];            }        }        check(tot);    }}/*16 91 41 51 62 42 52 63 43 53 61 4 2 5 3 6*/


0 0
原创粉丝点击