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

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

#include
#include
#include
#include
#include
#include
#define SF scanf
#define PF printf
using 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);
    }
}
/*
1
6 9
1 4
1 5
1 6
2 4
2 5
2 6
3 4
3 5
3 6
1 4 2 5 3 6
*/



你可能感兴趣的:(数据结构,BZOJ)