题目链接:https://codeforces.com/contest/1850/problem/H
题目的意思是给你n个人,与m对关系,根据这些关系来计算出是否能全部满足。
题目很好想,把这些人看成点,然后距离是权值,开了一个vector<pair<int,int>> g[N]来存储节点与值,因此可以看成一个森林,因为数轴上的点可以看成是无穷的,只要把遍历最开始的那个人的为之前看成0即可实现。
直接看代码
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define endl "\n"
const int N = 2e5;
int d[N];//度
int vi[N];//第i个点是否访问
int wi[N],ans[N];//wi[i]第i个节点当前的权值,ans[i]是这个点是否满足重复的
vector<pair<int,int>> g[N];//存边与权值,一个正权值一个负权值
void dfs(int now,int root,int w){//分别存储当前节点,父节点,父节点权值
for(auto [y,wn]:g[now]){
if(y==root)continue;
int k=w+wn;
if(vi[y]){//如果这个点被访问过
if(wi[y]!=k)ans[y]=1;//如果两次权值计算结果不相同那么就不对
continue;//遍历过了就说明他的孩子也遍历过了
}
vi[y]=1;//已经访问
wi[y]=k;//给予权值
dfs(y,now,k);//递归
}
}
void ChiefNing()
{
int n,m;
cin>>n>>m;
for(int i=1;i<=n;i++){
g[i].clear();
d[i]=0;
vi[i]=0;
wi[i]=0;
ans[i]=0;
}
for(int i=0;i<m;i++){
int x,y,w;
cin>>x>>y>>w;
g[x].push_back({y,w});//x->y存正权值
g[y].push_back({x,-w});//y->x存负权值
d[x]++;
d[y]++;
}
for(int i=1;i<=n;i++){
if(vi[i])continue;//访问过了
vi[i]=1;
dfs(i,i,0);
wi[i]=0;
}
for(int i=1;i<=n;i++){
if(ans[i]==1){
cout<<"NO"<<endl;
return ;
}
}
cout<<"YES"<<endl;
}
signed main(void)
{
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
int _;
cin>>_;
while(_--)
ChiefNing();
return 0;
}
比较清楚,不多说了,大致意思是如果有一个c点,从a点和b点都可以到达c点,并且a和b点有值(已经访问),根据a,b两点来计算c的权值,如果不相等那么就设置为1