题解 P4578【[FJOI2018]所罗门王的宝藏】
题意
给出 $n\times m$ 的矩阵中 $k$ 个数,记为 $x_i,y_i,v_i$,问有没有序列 $p,q$ 满足 $v_i=p_{x_i}+q_{y_i}$。
$n,m,k\le1000$。
思路
学校模拟赛题,一眼差分约束,不过我忘了咋写。于是想出了一种不同的解法。
我们可以考虑行、列之间的差,如 $a_{i,j}=p_i+q_j,a_{i,j'}=p_i+q_{j'},a_{i,j}-a_{i,j'}=q_j-q_{j'}$。用这样的方法可以记录列与列之间的差,同理可以记录行与行之间的差,过程中,如果发现原先记录的与现在新发现的不一样,则为 No,否则为 Yes。
时间复杂度 $O(k^2)$。
上代码:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N=1e3+10;
int T,n,m,k;
int cnt,mat[N][N],h[N][N],l[N][N];
inline void init(){
memset(mat,-1,sizeof(mat));
memset(h,-1,sizeof(h));
memset(l,-1,sizeof(l));
}
struct point{
int x,y,v;
}addi[N];
int main(){
T=read();
while(T--){
n=read(),m=read(),k=read();
init();
bool fl=0;
for(int i=1;i<=k;i++){
int x=read(),y=read(),v=read();
if((~mat[x][y])&&mat[x][y]!=v){
puts("No");
fl=1;
}
mat[x][y]=v;
addi[i]=(point){x,y,v};
}
if(fl) goto nxt;
for(int A=1;A<=k;A++){
for(int B=1;B<=k;B++){
if(A!=B){
int i=addi[A].x,j=addi[A].y;
int ii=addi[B].x,jj=addi[B].y;
if(j==jj){
if((~h[i][ii])&&h[i][ii]!=mat[ii][j]-mat[i][j]){
puts("No");
goto nxt;
}else{
h[i][ii]=mat[ii][j]-mat[i][j];
h[ii][i]=mat[i][j]-mat[ii][j];
}
}
if(i==ii){
if((~l[j][jj])&&l[j][jj]!=mat[i][jj]-mat[i][j]){
puts("No");
goto nxt;
}else{
l[j][jj]=mat[i][jj]-mat[i][j];
l[jj][j]=mat[i][j]-mat[i][jj];
}
}
}
}
}
puts("Yes");
nxt:;
}
return 0;
}
再见 qwq~

浙公网安备 33010602011771号