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;
    }
    
  • 相关阅读:
    openJudge计算概论-谁考了第k名
    OpenJudge计算概论-求平均年龄
    OpenJudge计算概论-能被3,5,7整除的数
    OpenJudge计算概论-计算书费
    OpenJudge计算概论-计算三角形面积【海伦公式】
    OpenWrt 中安装配置Transmission
    OpenWrt中wifidog的配置及各节点页面参数
    Linux中后台执行任务
    通过ionice和nice降低shell脚本运行的优先级
    OpenWrt中对USB文件系统的操作, 以及读写性能测试
  • 原文地址:https://www.cnblogs.com/wxyww/p/bzoj3569.html
Copyright © 2011-2022 走看看