【BZOJ4500】矩阵
题面
http://darkbzoj.tk/problem/4500
题解
首先,一行或者一列,又加又减肯定是没有意义的,所以相当于每一行每一列都有一个值,交点的值等于它们相加。
设$dis[i] (1<=i<=n)$的含义为第$i$行加的值(可正可负)
$dis[n+j] (1<=j<=m)$的含义为第$j$列加的值的相反数(同上)
然后写成作差的形式,初一的$hxh$(话说$hxh$跟我现在的班主任$wsy$长得真像。。。。)告诉我们,减负数等于加正数,就是一个等式,可以用差分约束做,但是因为都是等式取到等号,所以直接用$dfs$判$dis$值是否满足每一条边的需求就可以了。
(这可能就是$zhhx$说的把每个点看做变量,方程看做一个边的典型例题?终于找到了)
#include<vector> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define N 2050 #define ri register int #define INF 1000000007 using namespace std; inline int read() { int ret=0,f=0; char ch=getchar(); while (ch<'0' || ch>'9') f|=(ch=='-'),ch=getchar(); while (ch>='0' && ch<='9') ret*=10,ret+=(ch-'0'),ch=getchar(); return f?-ret:ret; } int n,m,k,dis[N]; bool can=0; vector<int> to[N],len[N]; void clear() { memset(dis,0x3f,sizeof(dis)); for (ri i=1;i<=n+m;i++) to[i].clear(),len[i].clear(); } void add_edge(int u,int v,int l) { to[u].push_back(v); len[u].push_back(l); } bool dfs(int x) { for (ri i=0;i<to[x].size();i++) { int y=to[x][i]; if (dis[y]>INF) { dis[y]=dis[x]+len[x][i]; if (!dfs(y)) return 0; } else { if (dis[y]!=dis[x]+len[x][i]) return 0; } } return 1; } bool check() { for (ri i=1;i<=n+m;i++) if (dis[i]>INF) { dis[i]=0; if (!dfs(i)) return 0; } return 1; } int main() { int T=read(); while (T--) { n=read(); m=read(); k=read(); clear(); for (ri i=1;i<=k;i++) { int x=read(),y=read(),c=read(); add_edge(x,y+n,c); add_edge(y+n,x,-c); } puts(check()?"Yes":"No"); } return 0; }