CF1850H The Third Letter
题解
知识点:贪心,图论建模。
考虑对约束 a b d
建边 \(a \mathop{\to}\limits^d b\) 与 \(b \mathop{\to}\limits^{-d} a\) ,这里也可以建单向边,但需要缩点,会麻烦很多。
若约束是合法的,那么遍历整张图得到的点权是不会矛盾的。因此,我们在一个连通块内任取一个点作为 \(0\) 并开始遍历整张图,访问过的点直接根据边权赋值,并标记下次不需要访问。最后,只需要检查所有约束是否得到满足即可。
时间复杂度 \(O(n)\)
空间复杂度 \(O(n)\)
代码
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
vector<pair<int, int>> g[200007];
tuple<int, int, int> c[200007];
bool vis[200007];
ll val[200007];
bool dfs(int u) {
for (auto [v, w] : g[u]) {
if (vis[v]) continue;
vis[v] = 1;
val[v] = val[u] + w;
dfs(v);
}
return true;
}
bool solve() {
int n, m;
cin >> n >> m;
for (int i = 1;i <= n;i++) vis[i] = val[i] = 0, g[i].clear();
for (int i = 1;i <= m;i++) {
int u, v, d;
cin >> u >> v >> d;
g[u].push_back({ v,d });
g[v].push_back({ u,-d });
c[i] = { u,v,d };
}
for (int i = 1;i <= n;i++) {
if (vis[i]) continue;
dfs(i);
}
for (int i = 1;i <= m;i++) {
auto [u, v, d] = c[i];
if (val[v] != val[u] + d) return false;
}
cout << "YES" << '\n';
return true;
}
int main() {
std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int t = 1;
cin >> t;
while (t--) {
if (!solve()) cout << "NO" << '\n';
}
return 0;
}
本文来自博客园,作者:空白菌,转载请注明原文链接:https://www.cnblogs.com/BlankYang/p/17686543.html