一开始的想法是转化成一个n+m个未知数k个方程的方程组然后甩高斯消元法,但写完发现一是要TLE(经优化可以解决该问题),二是方程是否存在一组整数解不好判断(因为不知道线性无关的方程数量和未知数数量的大小关系0),交上去花样WA
后来发现是自己想多了,方程的想法没问题,但注意到一个方程只有两个未知数,因此我们将每个未知数当成一个点,一个方程当成一条边,边的权值就是这个方程的值,每扫到一个没有被标记的变量就强行赋值 1 进行DFS即可。
#include<cstdlib>
#include<cstdio>
#include<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
#include<vector>
using namespace std;
#define maxn 1005
int cntm,n,m,k;
void _read(int &x)
{
x=0; char ch=getchar(); bool flag=false;
while(ch<'0'||ch>'9'){if(ch=='-')flag=true;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0'; ch=getchar();} if(flag)x=-x;
return ;
}
struct edge
{
int to,d,next;
}e[maxn*2];int edge_ct,head[maxn*2];
void add(int x,int y,int z)
{
e[++edge_ct]=(edge){y,z,head[x]};head[x]=edge_ct;
e[++edge_ct]=(edge){x,z,head[y]};head[y]=edge_ct; return ;
}
bool v[maxn*2];int d[maxn*2];
void Init()
{
_read(n); _read(m); _read(k);edge_ct=0;
for(int i=1;i<=n+m;i++)head[i]=0;
int x,y,d;
for(int i=1;i<=k;i++){_read(x);_read(y);_read(d); add(x,y+n,d);}
return ;
}
void YES(){putchar('Y');putchar('e');putchar('s');putchar('\n');}
void NO(){putchar('N');putchar('o');putchar('\n');}
bool flag;
void DFS(int now)
{
int j;v[now]=true;
for(int id=head[now];id;id=e[id].next)
{
j=e[id].to;
if(!v[j])
{
d[j]=e[id].d-d[now];DFS(j);
if(!flag)return ;
}
else if(d[j]+d[now]!=e[id].d)
{
flag=false; return;
}
}
}
void work()
{
for(int i=1;i<=n+m;i++)v[i]=false;flag=true;
for(int i=1;i<=n+m;i++)if(!v[i]){d[i]=1; DFS(i); if(!flag)break;}
if(flag)YES();else NO();
return ;
}
int main()
{
freopen("in.txt","r",stdin);
int T;
scanf("%d",&T);
while(T--)
{
Init(); work();
}
return 0;
}