codecorces #782 E

这篇博客主要探讨了一个图论问题,给定n个节点和m条边,每条边带有特定的权值,权值为0、1或2。文章通过分析指出,由于012组合中只能同时存在两种,因此答案只可能在这三个数字中。文章利用并查集实现,对每个二进制位进行处理,确定在特定位上是否存在使得路径和为1的边,并通过查询操作找出任意两点间路径的边权 mex 值。最后,通过实例展示了如何处理查询并输出结果。
摘要由CSDN通过智能技术生成

题意,给出n个点,m条边.定义mex(wi,wi&wi+1,wi&wi+1&wi+2)为从u,到v的边权,给出q个查询,给出两个点之间的边权。

容易发现012只可能同时存在两个,所以答案只在这三个数之间,

因为如果存在1,就说明最后一位一定为1,就不可能通过与得到一个偶数,只能得到0

如果存在2,那么最后一位一定为0,就不可能得到奇数,只能得到0.

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 10;
struct t {
	int u, v, w;
}edge[maxn * 2];
int fa[maxn][30];
int find(int x, int id)
{
	if (fa[x][id] == -1) return x;
	return fa[x][id] == x ? x : fa[x][id] = find(fa[x][id], id);
}
int can[30][maxn];//考虑第i位时的某个点在与得到1之前是否存在经过一条偶数边
int main()
{
	int n, m;
	std::ios::sync_with_stdio(0);
	cin >> n >> m;
	for (int i = 1; i <= m; ++i)
		cin >> edge[i].u >> edge[i].v >> edge[i].w;
	for (int i = 0; i <= 29; ++i)
		for (int j = 1; j <= n; ++j)
			fa[j][i] = -1;
	for (int i = 0; i <= 29; ++i) {
		for (int j = 1; j <= m; ++j)
		{
			if ((edge[j].w >> i) & 1)
			{
				int fx = find(edge[j].u, i);
				int fy = find(edge[j].v, i);
				if (fx != fy)
					fa[fy][i] = fx;
			}
		}//这样为什么能说明是在奇数与的时候得不到1,是因为当前图在只考虑第i位时得到的连通分量
		//如果某两个点联通就说明在第i位来考虑,当前相与一定得不到1,因为第i位都是1
		if (i > 0) {
			for (int j = 1; j <= m; ++j)
				if (edge[j].w % 2 == 0) {
					int fx = find(edge[j].u, i);
					int fy = find(edge[j].v, i);
					can[i][fx] = 1;
					can[i][fy] = 1;
				}
		}
	}
	int q;
	cin >> q;
	for (int i = 1; i <= q; ++i) {
		int u, v;
		cin >> u >> v;
		int ans = 2;
		for (int j = 0; j <= 29; ++j) {
			if (find(u, j) == find(v, j))
			{
				ans = 0;
				break;
			}
		}//这已经说明路径之中存在0
		//所以只用后面不存在1即可
		//不是最低位不存在1,而是在考虑
		// 都是奇数边-》一条偶数边-》随便走
		//我只需要考虑所经过的奇数边进行与之后得不到1,就遇到一个偶数边,关闭最低位的情况即可
		if (ans != 0) {
			for (int i = 1; i <= 29; ++i)
				if (can[i][find(u, i)])
					ans = 1;
		}
		cout << ans << '\n';
	}
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值