zoukankan      html  css  js  c++  java
  • 便 加权并查集

    题目
    发现每一行,列的差都相等
    124235346

    1-2=2-3=3-4
    2-4=3-5=4-6

    1-2=2-3=4-5
    2-3=3-4=5-6
    再发现了这个神奇的规律后,就可以用带权并查集维护了。

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    #include <cmath>
    #define N 100005
    using namespace std;
    int T,n,m,num,fx[N],fy[N],wx[N],wy[N],min1[N],min2[N];
    bool flag;
    struct data{int x,y,val;}d[N];
    bool cmpx(data a,data b){return a.x<b.x;}
    bool cmpy(data a,data b){return a.y<b.y;}
    int findx(int x){
        if(x==fx[x])return x;
        int rt=findx(fx[x]);
        wx[x]+=wx[fx[x]];
        return fx[x]=rt;
    }
    bool addx(int a,int b,int w){
        if(findx(a)!=findx(b)){
            int fa=findx(a),fb=findx(b);
            fx[fa]=fb;
            wx[fa]=wx[b]+w-wx[a];
            return true;
        }
        else return wx[a]==wx[b]+w;
    }
    int findy(int x){
        if(x==fy[x])return x;
        int rt=findy(fy[x]);
        wy[x]+=wy[fy[x]];
        return fy[x]=rt;
    }
    bool addy(int a,int b,int w){
        if(findy(a)!=findy(b)){
            int fa=findy(a),fb=findy(b);
            fy[fa]=fb;
            wy[fa]=wy[b]+w-wy[a];
            return true;
        }
        else return wy[a]==wy[b]+w;
    }
    void pno(){printf("No
    ");}
    int main()
    {
        scanf("%d",&T);
        while(T--){
            flag=0;
            scanf("%d%d%d",&n,&m,&num);
            for(int i=1;i<=n;i++){fx[i]=i;wx[i]=0;}
            for(int i=1;i<=m;i++){fy[i]=i;wy[i]=0;}
            for(int i=1;i<=num;i++){
                scanf("%d%d%d",&d[i].x,&d[i].y,&d[i].val);
                if(d[i].val<0) flag=1;
            }
            if(flag==1){pno();continue;}
            sort(d+1,d+num+1,cmpx);
            for(int i=1;i<num;i++)
                if(d[i].x==d[i+1].x)
                    if(!addy(d[i].y,d[i+1].y,d[i].val-d[i+1].val))
                        flag=1;
            if(flag==1){pno();continue;}
            sort(d+1,d+num+1,cmpy);
            for(int i=1;i<num;i++)
                if(d[i].y==d[i+1].y)
                    if(!addx(d[i].x,d[i+1].x,d[i].val-d[i+1].val))
                        flag=1;
            if(flag==1){pno();continue;}
            memset(min1,0x7f,sizeof min1);
            memset(min2,0x7f,sizeof min2);
            for(int i=1;i<=num;i++){
                int rt=findx(d[i].x);
                min1[rt]=min(min1[rt],d[i].val-wx[d[i].x]);
            }
            for(int i=1;i<=n;i++){
                int rt=findx(i);
                min2[rt]=min(min2[rt],wx[i]);
            }
            for(int i=1;i<=n;i++)
                if(fx[i]==i&&min1[i]+min2[i]<0)
                    flag=1;
            if(flag==1){pno();continue;}
            printf("Yes
    ");
        }
        return 0;
    }
  • 相关阅读:
    .net core 实现默认图片
    解决ASP.NET Core部署到IIS,更新项目"另一个程序正在使用此文件,进程无法访问"
    c# 按位与,按位或
    找对象,贤妻良母vs事业型
    基于Redis的分布式锁和Redlock算法
    关于free如何知道要释放内存空间的长度问题(X86篇)
    OpenWrt开发教程(五)shell命令操作json api详解(jshn.sh)
    Linux常见错误码声明
    SDN实验---流表项对网络的影响
    delphi 给TComboBox 添加图标
  • 原文地址:https://www.cnblogs.com/Ren-Ivan/p/7746684.html
Copyright © 2011-2022 走看看