Description
有一个n*m的矩阵,初始每个格子的权值都为0,可以对矩阵执行两种操作:
1. 选择一行, 该行每个格子的权值加1或减1。
2. 选择一列, 该列每个格子的权值加1或减1。
现在有K个限制,每个限制为一个三元组(x,y,c),代表格子(x,y)权值等于c。问是否存在一个操作序列,使得操作完后的矩阵满足所有的限制。如果存在输出”Yes”,否则输出”No”。
Input
先输入一个T(T <= 5)代表输入有T组数据,每组数据格式为:
第一行三个整数n, m, k (1 <= n, m,k <= 1000)。
接下来k行,每行三个整数x, y, c。
Output
对于每组数据,输出Yes或者No。
Sample Input
2
2 2 4
1 1 0
1 2 0
2 1 2
2 2 2
2 2 4
1 1 0
1 2 0
2 1 2
2 2 1
2 2 4
1 1 0
1 2 0
2 1 2
2 2 2
2 2 4
1 1 0
1 2 0
2 1 2
2 2 1
Sample Output
Yes
No
对于一个限定(a,b)=c
将行和列分别用点表示
则在a和b+n之间连一条长度为c的边
满足f[a]+f[b+n]=c
然后dfs验证即可
#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>
using namespace std;
struct line
{
int s,t;
int x;
int next;
}a[100001];
int head[2001];
int edge;
inline void add(int s,int t,int x)
{
a[edge].next=head[s];
head[s]=edge;
a[edge].s=s;
a[edge].t=t;
a[edge].x=x;
}
int sx[2001];
bool v[2001];
inline bool dfs(int d)
{
bool flag=true;
int i;
for(i=head[d];i!=0;i=a[i].next)
{
int t=a[i].t;
if(!v[t])
{
v[t]=true;
sx[t]=a[i].x-sx[d];
if(!dfs(t))
flag=false;
}
else if(sx[t]+sx[d]!=a[i].x)
flag=false;
}
return flag;
}
int main()
{
int T;
scanf("%d",&T);
while(T>0)
{
T--;
int n,m,k;
scanf("%d%d%d",&n,&m,&k);
memset(a,0,sizeof(a));
memset(head,0,sizeof(head));
edge=0;
int i;
int aa,bb,cc;
for(i=1;i<=k;i++)
{
scanf("%d%d%d",&aa,&bb,&cc);
edge++;
add(aa,bb+n,cc);
edge++;
add(bb+n,aa,cc);
}
memset(v,false,sizeof(v));
memset(sx,0,sizeof(sx));
bool flag=true;
for(i=1;i<=n;i++)
{
if(!v[i])
{
sx[i]=1.0;
v[i]=true;
if(!dfs(i))
flag=false;
}
}
if(flag)
printf("Yes\n");
else
printf("No\n");
}
return 0;
}