【BZOJ3569】DZY Loves Chinese II

时间:2019-10-30
本文章向大家介绍【BZOJ3569】DZY Loves Chinese II,主要包括【BZOJ3569】DZY Loves Chinese II使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

【BZOJ3569】DZY Loves Chinese II

题面

bzoj

题目大意:

给你一张\(N(1\leq N\leq 10^5)\)个点\(M(1\leq M\leq 5\times 10^5)\)条边的无向图,有\(Q(1\leq Q\leq 5\times 10^4)\)次询问,每次询问问你删去\(K(1\leq K\leq 15)\)条给定边后图的连通性是否改变。

题解

首先有一个很自然的想法就是把这个图的dfs序搞出来。

考虑一下怎样删去边会造成连通性改变,就是当一条树边和覆盖它的返祖边全部都被删掉的情况。

这样的话,我们可以给每条非树边随机一个权值,树边的权值定为覆盖它的所有非树边的权值。

然后判断的话直接看下给定边集有没有一个子集边权异或和为\(0\)即可,这一点可以用线性基实现。

代码

#include <iostream> 
#include <cstdio> 
#include <cstdlib> 
#include <cstring> 
#include <cmath> 
#include <algorithm> 
#include <ctime> 
using namespace std; 
inline int gi() {
    register int data = 0, w = 1; 
    register char ch = 0; 
    while (!isdigit(ch) && ch != '-') ch = getchar(); 
    if (ch == '-') w = -1, ch = getchar(); 
    while (isdigit(ch)) data = 10 * data + ch - '0', ch = getchar(); 
    return w * data; 
} 
typedef unsigned long long ull; 
const int MAX_N = 1e5 + 5; 
struct Graph { int to, next; } e[MAX_N * 10]; 
int fir[MAX_N], e_cnt; 
void clearGraph() { memset(fir, -1, sizeof(fir)); e_cnt = 0; } 
void Add_Edge(int u, int v) { e[e_cnt] = (Graph){v, fir[u]}; fir[u] = e_cnt++; } 
ull Random() { return (ull)((long double)rand() / RAND_MAX * 1e19); } 
ull Xor[MAX_N * 10], val[MAX_N * 10];
int dfn[MAX_N], tim; 
void dfs(int x, int fa) { 
    dfn[x] = ++tim; 
    for (int i = fir[x]; ~i; i = e[i].next) {
        int v = e[i].to; if (v == fa) continue; 
        if (!dfn[v]) { 
            dfs(v, x), Xor[x] ^= Xor[v]; 
            val[i] = val[i ^ 1] = Xor[v]; 
        } else if (dfn[v] < dfn[x]) { 
            val[i] = val[i ^ 1] = Random(); 
            Xor[x] ^= val[i], Xor[v] ^= val[i]; 
        } 
    } 
} 
ull bs[64]; 
bool insert(ull v) { 
    for (int i = 63; ~i; i--) 
        if (v >> i & 1ll) { 
            if (!bs[i]) return bs[i] = v, 1; 
            v ^= bs[i]; 
        } 
    return 0; 
} 
int N, M; 

int main () {
#ifndef ONLINE_JUDGE 
    freopen("cpp.in", "r", stdin);
#endif 
    srand(time(NULL)); 
    clearGraph(); 
    N = gi(), M = gi(); 
    for (int i = 1; i <= M; i++) { 
        int u = gi(), v = gi(); 
        Add_Edge(u, v), Add_Edge(v, u); 
    } 
    dfs(1, 0); 
    int Q = gi(), tot = 0; 
    while (Q--) { 
        memset(bs, 0, sizeof(bs)); 
        int K = gi();
        bool flag = 1; 
        while (K--) { 
            int num = gi() ^ tot; 
            if (!insert(val[(num - 1) << 1])) flag = 0; 
        } 
        tot += flag; 
        puts(flag ? "Connected" : "Disconnected"); 
    } 
    return 0; 
} 

原文地址:https://www.cnblogs.com/heyujun/p/11765119.html