P4578 [FJOI2018]所罗门王的宝藏
之前的博客markdown出锅了 ̄□ ̄||,又重新写了一遍
题意就是一个$n$ $\times$ $m$的矩阵,一开始全是零,你可以把每一行或每一列都加1或减1,要求特定区域的值与要求值相等
我们设$x_i$为第$i$行的数变化的多少,设$y_j$为第$j$列的数变化的多少,如果我们要求第$i$行,第$j$列的数为$x$,那么我们可以得到
$x_i$-$y_j$=$num$转换成不等式得到$\begin{cases}x_i-y_j \le num\\y_j-x_i \le -num \end{cases}$满足差分约束条件,这道题就变成了个差分约束板子
PS.差分约束本来是专门写了博客讲的,但是写糊了,就不打算重新写了,直接粘代码:
1 #include <iostream>
2 #include <algorithm>
3 #include <cstdio>
4 #include <queue>
5 #include <cstring>
6 #define inl inline
7 #define reg register
8 using namespace std;
9 int t,n,m,k;
10 int x,y,c;
11 struct node{
12 int to,w,next;
13 }ed[1000005];
14 int head[1000005],tot[1000005],dis[1000005],vis[1000005],cnt;
15 inl void add(int u,int v,int w){
16 ed[++cnt].to=v;
17 ed[cnt].w=w;
18 ed[cnt].next=head[u];
19 head[u]=cnt;
20 }
21 inl bool spfa(int s){
22 queue<int> q;
23 q.push(s);memset(vis,0,sizeof(vis));
24 for(int i = 1 ; i <= m + n ; ++i) dis[i] = 2003518617;
25 dis[s]=0;vis[s]=1;
26 while (!q.empty()){
27 int x=q.front();
28 q.pop();vis[x]=0;
29 for (reg int i = head[x];i;i=ed[i].next){
30 int to=ed[i].to;
31 if (dis[to]>dis[x]+ed[i].w){
32 dis[to]=dis[x]+ed[i].w;
33 if (!vis[to]){
34 vis[to]=1;tot[to]++;
35 if (tot[to]==n + m) return false;
36 q.push(to);
37 }
38 }
39 }
40 }
41 return true;
42 }
43 int main(){
44 scanf ("%d",&t);
45 while (t--){
46 memset(head,0,sizeof(head));cnt=0;memset(ed,0,sizeof(ed));memset(tot,0,sizeof(tot));
47 scanf ("%d%d%d",&n,&m,&k);
48 for (reg int i = 1;i <= n+m;i++) add(0,i,0);
49 for (reg int i = 1;i <= k;i++){
50 scanf ("%d%d%d",&x,&y,&c);
51 add(x,y+n,c);add(y+n,x,-c);
52 }
53 if (!spfa(0)) cout<<"No"<<endl;
54 else cout<<"Yes"<<endl;
55 }
56 return 0;
57 }