BZOJ4500: 矩阵

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

Sample Output

Yes
No
 
丝帛题,设对于第i行我们共进行了Ai次+1操作,对于第j列我们共进行了Bj次+1操作,那么每个格点的值就变成了Ai+Bj。
问题转化成判定若干个类同Ai+Bj=x的方程是否有解,用类似二分图染色的方法dfs一下就行了。
#include<cstdio>
#include<cctype>
#include<queue>
#include<cstring>
#include<algorithm>
#define rep(i,s,t) for(int i=s;i<=t;i++)
#define dwn(i,s,t) for(int i=s;i>=t;i--)
#define ren for(int i=first[x];i;i=next[i])
using namespace std;
const int BufferSize=1<<16;
char buffer[BufferSize],*head,*tail;
inline char Getchar() {
	if(head==tail) {
		int l=fread(buffer,1,BufferSize,stdin);
		tail=(head=buffer)+l;
	}
	return *head++;
}
inline int read() {
    int x=0,f=1;char c=Getchar();
    for(;!isdigit(c);c=Getchar()) if(c=='-') f=-1;
    for(;isdigit(c);c=Getchar()) x=x*10+c-'0';
    return x*f;
}
const int maxn=2010;
int n,m,vis[maxn],val[maxn],first[maxn],next[maxn<<1],to[maxn<<1],dis[maxn<<1],e;
void AddEdge(int u,int v,int w) {
	to[++e]=v;dis[e]=w;next[e]=first[u];first[u]=e;
	to[++e]=u;dis[e]=w;next[e]=first[v];first[v]=e;
}
int dfs(int x) {
	vis[x]=1;
	ren {
		if(vis[to[i]]&&val[to[i]]+val[x]!=dis[i]) return 0;
		else if(!vis[to[i]]) {
			val[to[i]]=dis[i]-val[x];
			if(!dfs(to[i])) return 0;
		}
	}
	return 1;
}
void solve() {
	n=read();m=read();e=0;
	rep(i,1,n+m) vis[i]=first[i]=0;
	dwn(i,read(),1) {
		int x=read(),y=read(),v=read();
		AddEdge(x,y+n,v);
	}
	rep(i,1,n+m) if(!vis[i]&&!dfs(i)) {
		puts("No");return;
	} 
	puts("Yes");
}
int main() {
	dwn(T,read(),1) solve();
	return 0;
}

  

posted @ 2016-05-21 12:58  wzj_is_a_juruo  阅读(202)  评论(0编辑  收藏  举报