AT2033 【マス目と整數 / Grid and Integers】
阿新 • • 發佈:2020-11-19
AT2033 【マス目と整數 / Grid and Integers】
題意
給定一個 $ R \times C $ 的矩陣,有一些位置的數已經被固定了,每個格子中只能有非負整數
詢問是否有一種填數方案使得任意一個$ 2 \times 2 $ 的子矩陣中有對角線之和相等
題解
考慮化簡題目要求
$ a_{i,j} + a_{i+1,j+1} = a_{i+1,j} + a_{i,j+1} $
$ a_{i,j} - a{i,j+1} = a_{i+1,j+1} - a_{i+1,j+1} $
同理有
$ a_{i,j} - a_{i+1,j} = a_{i,j+1} - a_{i+1,j+1} $
考慮構造 $ a_{i,j} = x_i + y_j $
如果存在可能的x序列和y序列
那麼對於每個子矩陣限制條件一定滿足
則原問題轉化為給定一些形如 $ x_i + y_j = val_k $ 的限制,能否構造出符合條件的序列
顯然任意兩個 $x_i$ 之間都不影響 同理$y_i$也是
於是考慮連邊,所成圖一定是若干個個二分圖
考慮給每個節點染色使得點權之和等於邊權
按照套路,先嚐試不考慮非負的限制,隨便構造出一組方案
顯然隨便找一個點賦個權值進行染色即可,顯然如果沒有限制相互矛盾這樣一定可以構造出一種方案
之後考慮調整一波,使得每個點非負,把每個二分圖的搜尋樹畫出來,容易發現對於一個點x,如果一個點增加了K,那麼為了滿足限制條件,所有點都會相應的加K或減K
所以只要在一種構造方案中有最小的 $x_i$ 和 $y_i$相加為非負數就一點有可行方案
程式碼很簡單
#include<bits/stdc++.h> using namespace std; #define LL long long inline LL read() { LL f = 1,x = 0; char ch; do { ch = getchar(); if(ch == '-') f = -1; }while(ch < '0'||ch > '9'); do { x= (x<<3) + (x<<1) + ch - '0'; ch = getchar(); }while(ch >= '0' && ch <= '9'); return f*x; } const int MAXN = 100000 + 10; int R,C; int N; bool vis[MAXN<<1]; vector<pair<int,LL> >G[MAXN<<1]; LL col[MAXN<<1]; int rt[MAXN<<1],tot; vector<int>Sta[MAXN<<1]; inline bool dfs(int x) { vis[x] = 1; Sta[tot].push_back(x); bool flag = 1; for(int i=0;i<G[x].size();i++) { LL v = G[x][i].first,w = G[x][i].second; if(vis[v]){ if(col[v] + col[x] != w) return false;} else { col[v] = w - col[x]; flag &= dfs(v); if(!flag) return false; } } return flag; } inline bool check(int x) { LL res1 = 1LL<<62,res2 = 1LL<<62; for(int i=0;i<Sta[x].size();i++) { int v = Sta[x][i]; if(v > R) res2 = min(res2 , col[v]); else res1 = min(res1, col[v]); } return res1 + res2 >= 0; } int main() { R = read(),C = read(); N = read(); for(int i=1;i<=N;i++) { int x = read(),y = read(),w = read(); G[x].push_back(make_pair(y+R,w)); G[y+R].push_back(make_pair(x,w)); } bool flag = 1; for(int i=1;i<=R+C;i++) if(!vis[i]) rt[++tot] = i,col[i] = 0,flag &= dfs(i); if(!flag) { printf("No\n");return 0;} for(int i=1;i<=tot;i++) flag &= check(i); if(!flag) printf("No\n"); else printf("Yes\n"); }