bzoj 4500 矩陣
阿新 • • 發佈:2020-08-13
我們可以把行操作看成加一,把列操作看成減一。
假如,有一個限制條件是C[i][j] = z
我們可以把它看成d[i] - d[j] = z;
這樣,我們就可以用帶權並查集來維護,判斷是否發生衝突就解決了。
當合並時 d[fx] = z - d[i] + d[j]
我們可以推一下這個式子 ,我們把上面那個移項就會變成 z-d[j]+d[i]
這樣直接合並就行了
程式碼
#include<iostream> #include<cstdio> #include<algorithm> using namespace std; int T,n,m,k,flag; int fa[2010],d[2010],x[1010],y[1010],z[1010]; inline int read() { int s = 0, w = 1; char ch = getchar(); while(ch < '0' || ch > '9'){if(ch == '-') w = -1; ch = getchar();} while(ch >= '0' && ch <= '9'){s= s * 10+ch - '0'; ch = getchar();} return s * w; } int find(int x)//邊帶權並查集 { if(fa[x] == x) return x; int root = find(fa[x]); d[x] += d[fa[x]]; return fa[x] = root; } int main() { T = read(); while(T--) { n = read(); m = read(); k = read(); flag = 0; for(int i = 1; i <= n; i++) fa[i] = i,d[i] = 0; for(int i = 1; i <= m; i++) fa[i+n] = n+i,d[n+i] = 0; for(int i = 1; i <= k; i++) x[i] = read(), y[i] = read() + n, z[i] = read();//要讀完一組資料 for(int i = 1; i <= k; i++) { int xx = find(x[i]), yy = find(y[i]); if(xx != yy)//如果不在一個集合就合併 { fa[xx] = yy; d[xx] = z[i] - d[x[i]] + d[y[i]]; } else { if(d[x[i]] - d[y[i]] != z[i]) flag = 1;//在一個集合判斷是否衝突 } } if(flag == 1) cout<<"No"<<endl; else cout<<"Yes"<<endl; } return 0; }
有個問題。,就是不能把列看成加,把行看成減來做。但這樣就會出錯
這個問題,很奇怪,我也不知道為什麼QAQ。