bzoj 4500 矩阵 题解

题意:
有一个 $ n * m $ 的矩阵,初始每个格子的权值都为 $ 0 $,可以对矩阵执行两种操作:

  1. 选择一行,该行每个格子的权值加1或减1。
  2. 选择一列,该列每个格子的权值加1或减1。

现在有 $ K $ 个限制,每个限制为一个三元组 $ (x,y,c) $ ,代表格子$ (x,y) $ 权值等于 $ c $ 。问是否存在一个操作序列,使得操作完后的矩阵满足所有的限制。如果存在出” $ Yes $ ”,否则输出” $ No $ ”。

这道题是个一个查分约束题,它给出 $ K $ 个条件要求即$ (x,y) $ 的权值为 $ c $ 我们可以看作 $ x $ 行的变换量 $ add[x] $ ,与第 $ y $ 列的变化量 $ add[y] $ 的和等于 $ c $ ,由于我们设置的是变化量所以是正还是负就无所谓~,所以我们可以写出 $ add[x]+add[y]=c $

等价于 $ add[y]-(-add[x])=c $

等价于 $ add[y]-(-add[x]) \geq c $ && $ add[y]-(-add[x]) \leq c $

等价于 $ add[y]-add[x]^\geq c $ && $ add[x]^-add[y] \geq -c $

然后就可以由 $ x->y $ 连一条长为 $ c $ 的边,由 $ y->x $ 连一条长为 $ -c $ 的边

至于为啥

由于列与行要区分,那么令列加上 $ n $ 即可

代码

#include<bits/stdc++.h>
using namespace std;
const int size=2010;
int head[size],Next[2*size],ver[2*size],edge[2*size],deg[size],tot;
int v[size],dis[size];
int n,m,k,T;
queue<int>q;
inline int read(){
   int x=0,f=1;
   char ch=getchar();
   while(ch<'0'||ch>'9'){
       if(ch=='-')
           f=-1;
       ch=getchar();
   }
   while(ch>='0'&&ch<='9'){
       x=(x<<1)+(x<<3)+(ch^48);
       ch=getchar();
   }
   return x*f;
}
void add(int x,int y,int z){
   ver[++tot]=y;edge[tot]=z;Next[tot]=head[x];head[x]=tot;
}
bool spfa(){
   while(q.size()) q.pop();
   memset(v,0,sizeof(v));
   memset(deg,0,sizeof(deg));
   memset(dis,0x3f,sizeof(dis));
   dis[0]=0;v[0]=1;q.push(0);
   while(q.size()){
       int x=q.front();q.pop();v[x]=0;
       if(deg[x]==n+m-1) return 0;
       deg[x]++;
       for(int i=head[x];i;i=Next[i]){
           int y=ver[i];
           if(dis[y]>dis[x]+edge[i]){
               dis[y]=dis[x]+edge[i];
               if(!v[y]){
                   v[y]=1;
                   q.push(y);
               }
           }
       }
   }
   return 1;
}
int main(){
   scanf("%d",&T);
   while(T--){
       memset(head,0,sizeof(head));tot=0;
       n=read();m=read();k=read();
       for(int i=1;i<=k;++i){
           int x,y,z;
           x=read();y=read();z=read();
           add(x,y+n,z);
           add(y+n,x,-z);
       }
       for(int i=1;i<=n+m;++i){
           add(0,i,0);
       }
       if(spfa()) printf("Yes\n");
       else printf("No\n");
   }
   return 0;
}

原文地址:https://www.cnblogs.com/donkey2603089141/p/11819115.html

时间: 2024-11-10 14:07:54

bzoj 4500 矩阵 题解的相关文章

BZOJ 4500: 矩阵 差分约束

题目链接: http://www.lydsy.com/JudgeOnline/problem.php?id=4500 题解: 从行向列建边,代表一个格子a[i][j],对每个顶点的所有操作可以合并在一起用sum[xi]表示, 那么题目相当于是要求sum[xi]+sum[xj]==a[xi][xj]: 等价于:sum[xj]-(-sum[xi])==a[xi][xj] 等价于:sum[xj]-sum'[xi]<=a[xi][xj] && sum[xj]-sum'[xi]>=a[x

【BZOJ 4500 矩阵】

Time Limit: 1 Sec  Memory Limit: 256 MBSubmit: 390  Solved: 217[Submit][Status][Discuss] Description 有一个n*m的矩阵,初始每个格子的权值都为0,可以对矩阵执行两种操作: 1. 选择一行, 该行每个格子的权值加1或减1. 2. 选择一列, 该列每个格子的权值加1或减1. 现在有K个限制,每个限制为一个三元组(x,y,c),代表格子(x,y)权值等于c.问是否存在一个操作序列,使得操作完后的矩阵满

bzoj 4500: 矩阵【差分约束】

(x,y,z)表示格子(x,y)的值为z,也就是x行+y列加的次数等于z,相当于差分约束的条件,用dfs判断冲突即可. #include<iostream> #include<cstdio> #include<cstring> using namespace std; const int N=2005; int T,n,m,k,cnt,p,h[N],va[N],f; bool v[N]; struct qwe { int ne,to,va; }e[N<<1]

BZOJ 1059 矩阵游戏(神奇的二分图匹配)

题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=1059 题意:给出一个N*N的01矩阵.有两种操作:(1)交换任意两行:(2)交换任意两列.问最后能否使得主对角线上全部为1? 思路:我们发现,对于同一行的两个1,比如 (i,j)和(i,j+1),无论如何我们也不能把这两个1都移动到主对角线上,换句话说,最多能够将其中一个1移动到主对角线上.因为,若我们想将这两 个同时移动到主对角线上,不妨设为(i1,i1),(i2,i2).首先,我们

BZOJ 1179 Atm 题解

BZOJ 1179 Atm 题解 SPFA Algorithm Tarjan Algorithm Description Input 第一行包含两个整数N.M.N表示路口的个数,M表示道路条数.接下来M行,每行两个整数,这两个整数都在1到N之间,第i+1行的两个整数表示第i条道路的起点和终点的路口编号.接下来N行,每行一个整数,按顺序表示每个路口处的ATM机中的钱数.接下来一行包含两个整数S.P,S表示市中心的编号,也就是出发的路口.P表示酒吧数目.接下来的一行中有P个整数,表示P个有酒吧的路口

函数式trie思想 &amp; Bzoj 3261 &amp; 3166 题解

[原题1] 3261: 最大异或和 Time Limit: 10 Sec  Memory Limit: 512 MB Submit: 497  Solved: 215 [Submit][Status] Description 给定一个非负整数序列 {a},初始长度为 N. 有   M个操作,有以下两种操作类型: 1 .A x:添加操作,表示在序列末尾添加一个数 x,序列的长度 N+1. 2 .Q l r x:询问操作,你需要找到一个位置 p,满足 l<=p<=r,使得: a[p] xor a[

BZOJ 1008 越狱 题解 裸快速幂

BZOJ 1008 越狱 题解 裸快速幂 1008: [HNOI2008]越狱 Time Limit: 1 Sec  Memory Limit: 162 MBSubmit: 7887  Solved: 3372[Submit][Status][Discuss] Description 监狱有连续编号为1...N的N个房间,每个房间关押一个犯人,有M种宗教,每个犯人可能信仰其中一种.如果相邻房间的犯人的宗教相同,就可能发生越狱,求有多少种状态可能发生越狱 Input 输入两个整数M,N.1<=M<

[BZOJ 1179]ATM题解 Tarjan缩点+SPFA

[BZOJ 1179]ATM题解 Tarjan缩点+SPFA Description Input 第一行包含两个整数N.M.N表示路口的个数,M表示道路条数.接下来M行,每行两个整数,这两个整数都在1到N之间,第i+1行的两个整数表示第i条道路的起点和终点的路口编号.接下来N行,每行一个整数,按顺序表示每个路口处的ATM机中的钱数.接下来一行包含两个整数S.P,S表示市中心的编号,也就是出发的路口.P表示酒吧数目.接下来的一行中有P个整数,表示P个有酒吧的路口的编号 Output 输出一个整数,

斜率优化专题3——bzoj 3156 防御准备 题解

[原题] 3156: 防御准备 Time Limit: 10 Sec  Memory Limit: 512 MB Submit: 198  Solved: 107 [Submit][Status] Description Input 第一行为一个整数N表示战线的总长度. 第二行N个整数,第i个整数表示在位置i放置守卫塔的花费Ai. Output 共一个整数,表示最小的战线花费值. Sample Input 10 2 3 1 5 4 5 6 3 1 2 Sample Output 18 HINT