个人技术分享

题目链接:The Third Letter

本道题目就是带权并查集的模板题,但又好久没学忘了,再复习一遍。。。

路径压缩函数模板:

int root(int x){
	if(pre[x]!=x){
		int t=root(pre[x]);
		d[x]+=d[pre[x]];
		pre[x]=t;
	}
	return pre[x];
}

之后就模拟一下就行了,判断两个士兵是否在一个集合里面,如果在一个集合里面,那么就判断两个人的位置有没有冲突,如果不在一个集合里面,那么就把他们合并到一个集合里面。

 对于 d [ fx ] = d [ y ] - d [ x ] + z 的理解:

首先合并集合 pre [ fx ] = fy,那么路径也要合并,如图要求d[fx],那么就是求 ? 。

已知 d [ x ] + ? - d [ y ] = z 可以推导出该公式。

代码附上:

#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 2e5+5;
int n,m;
int pre[N],d[N];

int root(int x){
	if(pre[x]!=x){
		int t=root(pre[x]);
		d[x]+=d[pre[x]];
		pre[x]=t;
	}
	return pre[x];
}

void init(){
	for(int i=1;i<=n;i++)pre[i]=i;
	for(int i=1;i<=n;i++)d[i]=0;
}

void solve(){
	cin>>n>>m;
	bool flag=true;
	init();

	while(m--){
		int x,y,z;cin>>x>>y>>z;
		int fx=root(x);
		int fy=root(y);
		if(fx!=fy){
			pre[fx]=fy;
			d[fx]=d[y]-d[x]+z;
		}
		else {
			if(d[x]-d[y]!=z){
				flag=false;
			}
		}
	}

	if(flag)cout<<"YES"<<"\n";
	else cout<<"NO"<<"\n";

}

signed main(){
	ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
	int t;cin>>t;
	while(t--){
		solve();
	}

	return 0;
}