bzoj4500 -- 差分约束
令a[i]表示第i行总共加了a[i],a[j]表示第j列总共加了a[j],得到k个方程:
a[i1]+a[j1]=c1
a[i2]+a[j2]=c2
...
a[ik]+a[jk]=ck
将i,j看成点,一遍dfs求出a并判断是否合法即可。
代码:
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 #define N 2010 7 struct Edge{ 8 int nx,t,w; 9 }e[N]; 10 int i,j,k,n,m,x,y,z,d[N],T,Num,h[N]; 11 bool b[N],f; 12 inline void Add(int x,int y,int z){e[++Num].t=y;e[Num].nx=h[x];e[Num].w=z;h[x]=Num;} 13 inline void Dfs(int x){ 14 if(!f)return;b[x]=1; 15 for(int i=h[x];i;i=e[i].nx) 16 if(!b[e[i].t]){ 17 d[e[i].t]=e[i].w-d[x]; 18 Dfs(e[i].t); 19 }else if(d[e[i].t]+d[x]!=e[i].w){ 20 f=0;break; 21 } 22 } 23 int main(){ 24 scanf("%d",&T); 25 while(T--){ 26 scanf("%d%d%d",&n,&m,&k); 27 memset(b,0,sizeof(b));f=1; 28 for(i=1,Num=0;i<=n+m;i++)h[i]=0; 29 for(i=1;i<=k;i++)scanf("%d%d%d",&x,&y,&z),Add(x,n+y,z),Add(n+y,x,z); 30 for(i=1;i<=n+m;i++) 31 if(!b[i]){ 32 Dfs(i); 33 if(!f){ 34 puts("No"); 35 break; 36 } 37 } 38 if(i>n+m)puts("Yes"); 39 } 40 return 0; 41 }