zoukankan      html  css  js  c++  java
  • bzoj 4500 矩阵

    链接

    我们可以把行操作看成加一,把列操作看成减一。

    假如,有一个限制条件是 \(C[i][j] = z\)

    我们可以把它看成 \(d[i] - d[j] = z\);

    这样,我们就可以用带权并查集来维护,判断是否发生冲突就解决了。

    当合并时 \(d[fx] = z - d[i] + d[j]\)

    我们可以推一下这个式子 ,我们把上面那个移项就会变成 \(z-d[j]+d[i]\)

    这样直接合并就行了

    代码

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    using namespace std;
    int T,n,m,k,flag;
    int fa[2010],d[2010],x[1010],y[1010],z[1010];
    inline int read()
    {
    	int s = 0, w = 1; char ch = getchar();
    	while(ch < '0' || ch > '9'){if(ch == '-') w = -1; ch = getchar();}
    	while(ch >= '0' && ch <= '9'){s= s * 10+ch - '0'; ch = getchar();}
    	return s * w;
    }
    int find(int x)//边带权并查集
    {
    	if(fa[x] == x) return x;
    	int root = find(fa[x]);
    	d[x] += d[fa[x]];
    	return fa[x] = root;
    }
    int main()
    {
    	T = read();
    	while(T--)
    	{
    		n = read(); m = read(); k = read(); flag = 0;
    		for(int i = 1; i <= n; i++) fa[i] = i,d[i] = 0;
    		for(int i = 1; i <= m; i++) fa[i+n] = n+i,d[n+i] = 0;
    		for(int i = 1; i <= k; i++) x[i] = read(), y[i] = read() + n, z[i] = read();//要读完一组数据
    		for(int i = 1; i <= k; i++)
    		{
    			int xx = find(x[i]), yy = find(y[i]);
    			if(xx != yy)//如果不在一个集合就合并
    			{
    				fa[xx] = yy;
    				d[xx] = z[i] - d[x[i]] + d[y[i]]; 
    	    	        }
    			else
    			{
    				if(d[x[i]] - d[y[i]] != z[i]) flag = 1;//在一个集合判断是否冲突
    			}
    		}
    		if(flag == 1) cout<<"No"<<endl;
    		else cout<<"Yes"<<endl;
    	}
    	return 0;
    }
    
    

    有个问题。,就是不能把列看成加,把行看成减来做。但这样就会出错

    这个问题,很奇怪,我也不知道为什么QAQ。

  • 相关阅读:
    Python文件File方法
    python的slice notation的特殊用法
    函数
    字典
    python 笔记7
    列表解析与生成器
    [CenOS7][Mac] MAC环境中dubbo连接zookeeper超时
    [JAVA][Thread] 实现Runnable接口和继承Thread类创建线程哪种方式更好?
    [Java] String字符常量类型作为参数传递的一些问题
    [JAVA]hashCode()和identityHashCode()的区别
  • 原文地址:https://www.cnblogs.com/genshy/p/13498958.html
Copyright © 2011-2022 走看看