【BZOJ4500】矩阵 DFS

一开始的想法是转化成一个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;
}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值