BZOJ 3563 DZY Loves Chinese / BZOJ 3569 DZY Loves Chinese II 随机化+高斯消元解异或方程组

题目大意:给出一个无向图,问删掉k条边的时候,图是否联通。

思路:虽然我把这两个题放在了一起,但是其实这两个题可以用完全不同的两个解法来解决。

第一个题其实是DZY出错了。。。把每次的边数也异或了,那就直接用这个性质一个一个往后推就行了。。最后一个暴力求一下。。

第二个题才是本意啊。

听到做法的时候我惊呆了。。

首先是将整个图中拆出一个树,那么所有边就分为树边和非树边。将所有非树边都加一个随机权值。树边的权值是所有能够覆盖它的非树边的权值的异或和。

把整个图拆开的充要条件是拆掉一条树边,同时将所有覆盖它的非树边也要拆掉,这些边的异或和正好等于0.这个就可以用高斯消元解异或方程组来解决了。

神啊神啊神啊神啊。。。

CODE:

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define MAX 1000010
using namespace std;

struct Edge{
	int x,y,len;
	bool tree_edge;

	void Read() {
		scanf("%d%d",&x,&y);
	}
}edge[MAX];

int points,edges,asks;
int head[MAX],total = 1;
int next[MAX],aim[MAX];

bool v[MAX];
int _xor[MAX];

inline void Add(int x,int y)
{
	next[++total] = head[x];
	aim[total] = y;
	head[x] = total;
}

void BuildTree(int x,int last)
{
	v[x] = true;
	for(int i = head[x]; i; i = next[i])
		if(!v[aim[i]]) {
			edge[i >> 1].tree_edge = true;
			BuildTree(aim[i],x);
		}
}

void DFS(int x,int last)
{
	for(int i = head[x]; i; i = next[i])
		if(edge[i >> 1].tree_edge && aim[i] != last) {
			DFS(aim[i],x);
			edge[i >> 1].len = _xor[aim[i]];
			_xor[x] ^= _xor[aim[i]];
		}
}

int temp[MAX];

inline bool GaussElimination(int cnt)
{
	int k = 0,i;
	for(int j = 1 << 30; j; j >>= 1) {
		for(i = k + 1; i <= cnt; ++i)
			if(temp[i]&j)
				break;
		if(i == cnt + 1)	continue;
		swap(temp[i],temp[++k]);
		for(int i = 1; i <= cnt; ++i)
			if(temp[i]&j && i != k)
				temp[i] ^= temp[k];
	}
	return temp[cnt];
}

int main()
{
	srand(19970815);
	cin >> points >> edges;
	for(int i = 1; i <= edges; ++i) {
		edge[i].Read();
		Add(edge[i].x,edge[i].y);
		Add(edge[i].y,edge[i].x);
	}
	BuildTree(1,0);
	for(int i = 1; i <= edges; ++i)
		if(!edge[i].tree_edge) {
			edge[i].len = rand();
			_xor[edge[i].x] ^= edge[i].len;
			_xor[edge[i].y] ^= edge[i].len;
		}
	DFS(1,0);
	cin >> asks;
	int last_ans = 0;
	for(int cnt,x,i = 1; i <= asks; ++i) {
		scanf("%d",&cnt);
		//cnt ^= last_ans;
		for(int j = 1; j <= cnt; ++j) {
			scanf("%d",&x);
			x ^= last_ans;
			temp[j] = edge[x].len;
		}
		bool flag = !GaussElimination(cnt);
		if(!flag) {
			puts("Connected");
			++last_ans;
		}
		else	puts("Disconnected");
	}
	return 0;
}

时间: 2024-12-23 00:14:49

BZOJ 3563 DZY Loves Chinese / BZOJ 3569 DZY Loves Chinese II 随机化+高斯消元解异或方程组的相关文章

【BZOJ 2337】 2337: [HNOI2011]XOR和路径(概率DP、高斯消元)

2337: [HNOI2011]XOR和路径 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1170  Solved: 683 Description Input Output Sample Input Sample Output HINT Source Day2 [分析] 这题终于自己打出来了高斯消元.没有对比代码了... 很心酸啊..调试的时候是完全没有方向的,高斯消元还要自己一步步列式子然后消元解..[为什么错都不知道有时候 这题显然是不能

[BZOJ 3143][Hnoi2013]游走(高斯消元+期望)

Description 一个无向连通图,顶点从1编号到N,边从1编号到M. 小Z在该图上进行随机游走,初始时小Z在1号顶点,每一步小Z以相等的概率随机选 择当前顶点的某条边,沿着这条边走到下一个顶点,获得等于这条边的编号的分数.当小Z 到达N号顶点时游走结束,总分为所有获得的分数之和. 现在,请你对这M条边进行编号,使得小Z获得的总分的期望值最小. Solution 对于点u(u≠1):到达u的概率 f[u]=∑f[v]/d[v] (Edges(u,v)) 而f[1]=∑f[v]/d[v]+1

BZOJ 3143 HNOI2013 游走 高斯消元 期望

这道题是我第一次使用高斯消元解决期望类的问题,首发A了,感觉爽爽的.... 中文题目,就不翻大意了,直接给原题: 一个无向连通图,顶点从1编号到N,边从1编号到M. 小Z在该图上进行随机游走,初始时小Z在1号顶点,每一步小Z以相等的概率随机选 择当前顶点的某条边,沿着这条边走到下一个顶点,获得等于这条边的编号的分数.当小Z 到达N号顶点时游走结束,总分为所有获得的分数之和. 现在,请你对这M条边进行编号,使得小Z获得的总分的期望值最小. 输出最小的总分期望值. Solution: 这题贪心很明显

BZOJ 4004: [JLOI2015]装备购买 [高斯消元同余 线性基]

和前两(一)题一样,不过不是异或方程组了..... 然后bzoj的新数据是用来卡精度的吧..... 所有只好在模意义下做啦 只是巨慢无比 #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #include <bitset> using namespace std; typedef long lon

BZOJ 3569 DZY Loves Chinese II 高斯消元

题目大意:给定一个[魞歄连通图],多次询问当图中某k条边消失时这个图是否联通 强制在线 我们找到这个图的任意一棵生成树 然后对于每条非树边将其的权值赋为一个随机数 对于每条树边 我们将这条树边的权值设为所有覆盖这条树边的边权的异或和 那么图不连通当且仅当删除一条树边和覆盖这条树边的所有边集 而由于刚才的处理一条树边和覆盖这条边的所有边集的异或和为零 于是问题转化成了对于给定的k条边是否存在一个边权的异或和为零的子集 果断高斯消元 由于使用了随机化所以碰撞率极低 好方法学习了...构思真是巧妙 记

[Luogu P2973&amp;BZOJ 1778][USACO10HOL]赶小猪DOtP(高斯消元+期望)

Description 一个无向图,节点1有一个炸弹,在每个单位时间内,有可能在这个节点炸掉,也有p/q的概率随机选择一条出去的路到其他的节点上.问最终炸弹在每个节点上爆炸的概率. Solution 没错它就是BZOJ 1778…在bzoj上是权限题 炸弹最终爆炸的概率是1(可能是在无穷无尽的时间之后…),于是到达某一点的概率除以到达所有点的概率就是在这个节点上爆炸的概率 f[u]=∑f[v]*(1-p/q)/d[v] #include<iostream> #include<cstdio

BZOJ 3143 游走 | 数学期望 高斯消元

啊 我永远喜欢期望题 BZOJ 3143 游走 题意 有一个n个点m条边的无向联通图,每条边按1~m编号,从1号点出发,每次随机选择与当前点相连的一条边,走到这条边的另一个端点,一旦走到n号节点就停下.每经过一条边,要付出这条边的编号这么多的代价.现将所有边用1~m重新编号,使总代价的期望最小,求这个最小值. 题解 我们可以求出每条边的期望经过次数,然后贪心地让经过次数多的边编号小即可. 直接用边来列方程求经过次数似乎列不出来,我们借助点来列方程. 设x[u]为从某个点出发的次数的期望,v为与u

【BZOJ 4171】 4171: Rhl的游戏 (高斯消元)

4171: Rhl的游戏 Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 74  Solved: 33[Submit][Status][Discuss] Description RHL最近迷上一个小游戏:Flip it.游戏的规则很简单,在一个N*M的格子上,有一些格子是黑色,有一些是白色 .每选择一个格子按一次,格子以及周围边相邻的格子都会翻转颜色(边相邻指至少与该格子有一条公共边的格子 ),黑变白,白变黑.RHL希望把所有格子都变成白色的.不幸

BZOJ 3105: [cqoi2013]新Nim游戏 [高斯消元XOR 线性基]

以后我也要用传送门! 题意:一些数,选择一个权值最大的异或和不为0的集合 终于有点明白线性基是什么了...等会再整理 求一个权值最大的线性无关子集 线性无关子集满足拟阵的性质,贪心选择权值最大的,用高斯消元判断是否和已选择的线性相关 每一位记录pivot[i]为i用到的行 枚举要加入的数字的每一个二进制为1的位,如果有pivot[i]那么就异或一下(消元),否则pivot[i]=这个数并退出 如果最后异或成0了就说明线性相关... #include <iostream> #include &l