huangrenheluogu
2024-11-15 14:54:05
考虑充分条件,对于
考虑如果有两个位置
建图,对于一个连通块,找到一个基准点,算出每个点到这个点的相对大小,然后把所有点跑一遍暴力判断看看会不会弄成负数就好了。
需要思考的问题是对于一个位置,行、列都没有出现过,此时相当于差可以任意选择。所以不同连通块之间是不影响的。
考虑这是模拟赛题,保险起见行、列都跑了一次,其实只跑一个方向就是充要条件了。
#include<bits/stdc++.h>
#define int long long
#define pii pair<int, int>
#define fi first
#define se second
#define NO {puts("No");exit(0);}
using namespace std;
const int N = 1e5 + 5;
int n, m, k, x;
struct node{
int a, b, c;
}a[N];
inline void chkmin(int &x, int y){
if(x > y) x = y;
}
struct Graph{
vector<pii> G[N];
int dist[N], n, vis[N], minn[N], cnt;
inline void addedge(int x, int y, int z){
G[x].push_back({y, z});
G[y].push_back({x, -z});
// if(x == 12 || y == 12) cerr << x << ' ' << y << ' ' << z << endl;
}
inline void dfs(int x){
vis[x] = cnt;
chkmin(minn[cnt], dist[x]);
for(pii e : G[x]){
if(vis[e.fi]){
if(dist[e.fi] != dist[x] + e.se) NO;
continue ;
}
dist[e.fi] = dist[x] + e.se;
dfs(e.fi);
}
}
inline void solve(){
for(int i = 1; i <= n; i++){
if(!vis[i]){
dist[i] = 0;
cnt++;
dfs(i);
}
}
}
}L, C;
signed main(){
// freopen("zibi.in", "r", stdin);
// freopen("zibi.out", "w", stdout);
scanf("%lld%lld%lld", &n, &m, &k);
for(int i = 1; i <= k; i++){
scanf("%lld%lld%lld", &a[i].a, &a[i].b, &a[i].c);
}
sort(a + 1, a + k + 1, [&](node x, node y){
if(x.a == y.a) return x.b < y.b;
return x.a < y.a;
});
L.n = m, C.n = n;
for(int i = 1; i <= k; i++){
if(a[i].a == a[i - 1].a){
L.addedge(a[i - 1].b, a[i].b, a[i].c - a[i - 1].c);
}
}
L.solve();
// cerr << endl;
sort(a + 1, a + k + 1, [&](node x, node y){
if(x.b == y.b) return x.a < y.a;
return x.b < y.b;
});
for(int i = 1; i <= k; i++){
if(a[i].b == a[i - 1].b){
C.addedge(a[i - 1].a, a[i].a, a[i].c - a[i - 1].c);
if(a[i].a == 5387 || a[i].a == 41257){
// cerr << "test : " << a[i].a << ' ' << a[i].b << ' ' << a[i].c << endl;
// cerr << "test2 : " << a[i - 1].a << ' ' << a[i - 1].b << ' ' << a[i - 1].c << endl;
}
}
}
C.solve();
// for(int i = 1; i <= m; i++){
// if(C.vis[i] == 5219){
// cerr << i << ' ' << C.dist[i] << endl;
// }
// }
// cerr << endl;
for(int i = 1; i <= k; i++){
x = L.minn[L.vis[a[i].b]] - L.dist[a[i].b];
// cerr << a[i].b << ' ' << L.vis[a[i].b] << ' ' << a[i].c << ' ' << x << endl;
if(x + a[i].c < 0) NO;
x = C.minn[C.vis[a[i].a]] - C.dist[a[i].a];
// cerr << a[i].a << ' ' << a[i].b << ' ' << C.vis[a[i].a] << ' ' << a[i].c << ' ' << x << endl;
if(x + a[i].c < 0) NO;
}
puts("Yes");
return 0;
}