CF1850H-The Third Letter

14 阅读1分钟

CF1850H-The Third Letter

题目大意

在一条数轴上你需要分配 nn 个点的坐标,来满足 mm 个条件。每个条件有三个参数 a,b,wa,b,w ,表示 aa 的坐标比 bbww 。一个坐标上可以分配多个点。

询问你,存不存在一种分配方式,满足所有 mm 个条件。

题解

考虑建图,对于每个条件,可以建立两条边,[u,v,w][u,v,w] 表示 vvuuww 个坐标,[v,u,w][v,u,-w] 表示 uuvvw-w 个坐标。

遍历所有点跑 dfsdfs ,如果一个点没有被访问过,那么设置这个点在 00 上,然后 dfsdfsdfsdfs 过程中,如果遇到没有访问过的点,就根据边设置点的坐标。如果遇到访问过的点,就 checkcheck 是否与边的要求冲突。

#include<bits/stdc++.h>
#define ios ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define umap unordered_map
#define pq(x) priority_queue<x>
#define ppq(x) priority_queue<x,vector<x>,greater<x>>
#define endl '\n'
using namespace std;
using i128 = __int128;
const int mod =1e9+7;
template <typename T>void read(T&x){
    x=0;int f = 1;
    char c=getchar();
    for(;!isdigit(c);c=getchar())if(c=='-')f=-1;
    for(;isdigit(c);c=getchar())x=(x<<1)+(x<<3)+(c^48);
    x*=f;
}
template <typename T>void print(T x) {
     if (x < 0) { putchar('-'); x = -x; }
     if (x > 9) print(x / 10);
     putchar(x % 10 + '0');
}
#define int long long
const int N=2e5+5;
const int M=2e6+5;
int vis[N];
int poi[N];
vector<pair<int,int>> G[N];
int ans=1;
void dfs(int u)
{
	vis[u]=1;
	for(auto [v,w]:G[u])
	{
		if(vis[v])
		{
			if(poi[v]!=poi[u]+w) ans=0;
		}
		else
		{
			poi[v]=poi[u]+w;
			dfs(v);
		}	
	}
}
inline void solve()
{
	int n,m;
	cin>>n>>m;
	ans=1;
	for(int i=1;i<=n;i++) vis[i]=0,G[i].clear();
	for(int i=1;i<=m;i++)
	{
		int u,v,w;
		cin>>u>>v>>w;
		G[u].push_back({v,w});
		G[v].push_back({u,-w});
	}
	for(int i=1;i<=n;i++)
	{
		if(!vis[i])
		{
			poi[i]=0;
			dfs(i);
			
		}
	}
	if(ans) cout<<"YES"<<endl;
	else cout<<"NO"<<endl;
}

signed main()
{
	ios;
	int T=1;
	cin>>T;
	for(;T--;) solve();
	return 0;
}