zoukankan      html  css  js  c++  java
  • 【bzoj4500】矩阵 带权并查集

    题目描述

    有一个n*m的矩阵,初始每个格子的权值都为0,可以对矩阵执行两种操作:
    1. 选择一行, 该行每个格子的权值加1或减1。
    2. 选择一列, 该列每个格子的权值加1或减1。
    现在有K个限制,每个限制为一个三元组(x,y,c),代表格子(x,y)权值等于c。问是否存在一个操作序列,使得操作完后的矩阵满足所有的限制。如果存在输出”Yes”,否则输出”No”。

    输入

    先输入一个T(T <= 5)代表输入有T组数据,每组数据格式为:
    第一行三个整数n, m, k (1 <= n, m,k <= 1000)。
    接下来k行,每行三个整数x, y, c。

    输出

    对于每组数据,输出Yes或者No。

    样例输入

    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

    样例输出

    Yes
    No


    题解

    带权并查集

    如果把行操作看作加,列操作看作减,那么每个限制就是“某行操作比某列操作大多少”。

    使用带权并查集维护即可。

    注意多组数据要把数据读全。

    #include <queue>
    #include <cstdio>
    #include <cstring>
    #define N 1010
    using namespace std;
    int x[N] , y[N] , z[N] , f[N << 1] , r[N << 1];
    int find(int x)
    {
    	if(x == f[x]) return x;
    	int t = f[x];
    	f[x] = find(t) , r[x] += r[t];
    	return f[x];
    }
    int main()
    {
    	int T;
    	scanf("%d" , &T);
    	while(T -- )
    	{
    		int n , m , k , i , tx , ty;
    		scanf("%d%d%d" , &n , &m , &k);
    		for(i = 1 ; i <= k ; i ++ ) scanf("%d%d%d" , &x[i] , &y[i] , &z[i]) , y[i] += n;
    		for(i = 1 ; i <= n + m ; i ++ ) f[i] = i , r[i] = 0;
    		for(i = 1 ; i <= k ; i ++ )
    		{
    			tx = find(x[i]) , ty = find(y[i]);
    			if(tx != ty) f[tx] = ty , r[tx] = z[i] + r[y[i]] - r[x[i]];
    			else if(r[x[i]] - r[y[i]] != z[i]) break;
    		}
    		if(i > k) puts("Yes");
    		else puts("No");
    	}
    	return 0;
    }
    

     

  • 相关阅读:
    Macbook上如何把中文文本转成UTF-8
    防火墙学习笔记
    百万长连接并发的限制因素
    meminfo中的字段都是什么意思?
    维护TCP长连接时系统配置的参数net.ipv4.tcp_keepalive_time不生效
    小程序如何利用CSS画出箭头
    cephfs配额问题
    ceph机房断电之后重启遇到问题“Transaction order is cyclic. See system logs for details.”
    valgrind的使用方法
    程序员的创业经历
  • 原文地址:https://www.cnblogs.com/GXZlegend/p/7889288.html
Copyright © 2011-2022 走看看