• 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
    ");
       	else printf("No
    ");
       }
       return 0;
    }
    
  • 相关阅读:
    pgrep 查询进程的工具
    shell脚本中>/dev/null的含义
    一条命令批量替换多个文件中字符串
    Centos 6.4上面用Shell脚本一键安装vsftpd
    centos 卸载vsftpd方法
    Centos 6.4上面用Shell脚本一键安装mysql 5.6.15
    SHELL学习笔记----IF条件判断,判断条件
    CentOS挂载新硬盘
    Linux fdisk 命令
    Linux df 命令
  • 原文地址:https://www.cnblogs.com/donkey2603089141/p/11819115.html
Copyright © 2020-2023  润新知