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 }
bzoj4500

 

posted @ 2017-03-26 17:41  gjghfd  阅读(189)  评论(0编辑  收藏  举报