求此解的正确性
  • 板块CF891C Envy
  • 楼主yh2022mayu
  • 当前回复0
  • 已保存回复0
  • 发布时间2024/10/13 21:50
  • 上次更新2024/10/14 11:15:24
查看原帖
求此解的正确性
541786
yh2022mayu楼主2024/10/13 21:50

问题如标题

解法思路:先类似克鲁斯卡尔按顺序合并每条边,将一条边的端点改为合并了边权小于此边的所有边后端点所在并查寄的顶点,对于每个查询直接合并查询的边修改后的端点,有环则不行,没环则可以

代码:

#include<bits/stdc++.h>
#define x first
#define y second
#define pii pair<int, int>
#define vci vector<int>
#define psb push_back
using namespace std;
int p[500005][2];
vci hd[2];
void init(){
	for(int i = 1; i <= 500000; i++) p[i][0] = p[i][1] = i;
}
int find(int op, int u){
	if(u == p[u][op]) return u;
	return p[u][op] = find(op, p[u][op]);
}
bool mer(int op, int a, int b){
	a = find(op, a), b = find(op, b);
	if(a == b) return 0;
	hd[op].psb(a), hd[op].psb(b);
	p[a][op] = b;
	return 1;
}
void clr(int op){
	for(int i = 0; i < hd[op].size(); i++) p[hd[op][i]][op] = hd[op][i];
	hd[op].clear();
}
int n, m, q;
vci hv[500005];
pair<pii, int> e[500005];
signed main(){
	//ios::sync_with_stdio(false);
    //cin.tie(NULL);
    //cout.tie(NULL);
    //freopen(".in", "r", stdin);
    //freopen(".out", "w", stdout);
	srand(time(0));
	init();
	scanf("%d%d", &n, &m);
	for(int i = 1; i <= m; i++) scanf("%d%d%d", &e[i].x.x, &e[i].x.y, &e[i].y), hv[e[i].y].psb(i);
	for(int i = 1; i <= 500000; i++){
		for(int j : hv[i]) e[j].x.x = find(0, e[j].x.x), e[j].x.y = find(0, e[j].x.y);
		for(int j : hv[i]) mer(0, e[j].x.x, e[j].x.y);
	}
	cin >> q;
	while(q--){
		int x, fl = 1;
		scanf("%d", &x);
		while(x--){
			int id;
			scanf("%d", &id);
			fl &= mer(1, e[id].x.x, e[id].x.y);
		}
		if(fl) puts("YES");
		else puts("NO");
		clr(1);
	}
	return 0;
}
2024/10/13 21:50
加载中...