zoukankan      html  css  js  c++  java
  • bzoj3569 DZY Loves Chinese II

    题目链接

    problem

    给出一个(n)个点(m)条边的无向图,然后有(Q)次询问,每次询问会给出(k)条边,你需要回答删掉这(k)条边之后这个无向图还是不是连通。

    (nle 10^5,mle 5 imes 10^5,kle 15)

    solution

    先找出一个(dfs)树,考虑在什么情况下无向图会变得不连通。

    当且仅当存在一条树边,满足所有覆盖这条树边的返祖边和这条树边都被删除时,无向图不连通。

    那么如何判断是不是存在这样一条树边呢,我们可以给每条返祖边随机一个权值,每条树边的权值就是所有覆盖它的返祖边的权值异或和。对于一次查询,如果查询的边权线性相关说明一定能找到一个子集异或和为0,也就是满足无向图不连通的条件了。

    code

    /*
    * @Author: wxyww
    * @Date:   2020-05-25 16:14:15
    * @Last Modified time: 2020-05-25 16:47:10
    */
    #include<cstdio>
    #include<iostream>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    #include<vector>
    #include<ctime>
    #include<cmath>
    using namespace std;
    typedef long long ll;
    const int N = 500100;
    ll read() {
    	ll x = 0,f = 1;char c = getchar();
    	while(c < '0' || c > '9') {
    		if(c == '-') f = -1; c = getchar();
    	}
    	while(c >= '0' && c <= '9') {
    		x = x * 10 + c - '0'; c = getchar();
    	}
    	return x * f;
    }
    int n,m;
    struct node {
    	int v,nxt,w,id;
    }e[N << 1];
    
    int head[N],ejs = 1;
    void add(int u,int v,int id) {
    	e[++ejs].v = v;e[ejs].nxt = head[u];head[u] = ejs;e[ejs].id = id;
    }
    int vis[N],w[N];
    
    void dfs1(int u,int fa) {
    	vis[u] = 1;
    	for(int i = head[u];i;i = e[i].nxt) {
    		int v = e[i].v;
    		if(e[i].w || v == fa) continue;
    		if(vis[v]) {
    			e[i].w = e[i ^ 1].w = rand() + 1;
    			w[u] ^= e[i].w;w[v] ^= e[i].w;
    			continue;
    		}
    		dfs1(v,u);
    	}
    }
    
    void dfs2(int u,int fa) {
    	for(int i = head[u];i;i = e[i].nxt) {
    		int v = e[i].v;if(v == fa || e[i].w) continue;
    		dfs2(v,u);
    		w[u] ^= w[v];
    		e[i].w = e[i ^ 1].w = w[v];
    	}
    }
    
    int cnt,p[32];
    int ins(int x) {
    
    	// printf("!!!%d
    ",x);
    	
    	for(int i = 30;i >= 0;--i) {
    		if(x >> i & 1) {
    			if(!p[i]) {p[i] = x;return 1;}
    			x ^= p[i];
    		}
    	}
    	return 0;
    }
    void solve() {
    	int k = read(),flag = 0;
    	for(int i = 1;i <= k;++i) {
    		int x = read() ^ cnt;
    		// printf("%d ",x);
    		if(flag) continue;
    		if(!ins(e[x << 1].w)) {
    			puts("Disconnected");
    			flag = 1;
    			continue;
    		}
    	}
    	// puts("");
    	if(!flag) {
    		++cnt;
    		puts("Connected");
    	}
    }
    
    int main() {
    	// freopen("1.in","r",stdin);
    	n = read(),m = read();
    
    	for(int i = 1;i <= m;++i) {
    		int u = read(),v = read();
    		add(u,v,i);add(v,u,i);
    	}
    
    	dfs1(1,0);
    	dfs2(1,0);
    	int Q = read();
    	while(Q--) {
    		memset(p,0,sizeof(p));
    		solve();
    	}
    	return 0;
    }
    
  • 相关阅读:
    git常用指令 github版本回退 reset
    三门问题 概率论
    如何高效的学习高等数学
    数据库6 关系代数(relational algebra) 函数依赖(functional dependency)
    数据库5 索引 动态哈希(Dynamic Hashing)
    数据库4 3层结构(Three Level Architecture) DBA DML DDL DCL DQL
    梦想开始的地方
    java String字符串转对象实体类
    java 生成图片验证码
    java 对象之间相同属性进行赋值
  • 原文地址:https://www.cnblogs.com/wxyww/p/bzoj3569.html
Copyright © 2011-2022 走看看