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