题目链接: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;
}