HDU3038(How Many Answers Are Wrong)

链接:https://vjudge.net/problem/HDU-3038
思路:带权并查集,首先我们要考虑在什么情况下会出错,当且仅当某个区间开头和位置以及和都确定并且产生矛盾的时候,于是我们建立一个带权并查集,每个区间查询其左端点-1的节点(因为左端点也要算在和内)与右端点的节点的祖先节点,如果相同说明通过其他的操作已经可以推算出这个区间的值了(自行思考推理一下),只需要比对一下前后到祖先节点距离的差值是否等于给定的值即可,如果不等则说明没法推断出,则不会产生矛盾,此时将两个端点合并,并且更新各节点到祖先节点的距离。
代码:

#include<bits/stdc++.h>
using namespace std;

const int maxn = 200010;
int par[maxn];
int n,m;
int sum[maxn];

int getroot(int a){
    if(par[a]==a)return a;
    int p = par[a];
    par[a] = getroot(par[a]);
    sum[a]+=sum[p];//更新到祖先节点的距离
    return par[a];
}

int main(){
    while(~scanf("%d%d",&n,&m)){
        int res = 0;
        for(int i=0;i<=n;i++){
            par[i] = i;
            sum[i] = 0;
        }
        for(int i=0;i<m;i++){
            int u,v,w;
            scanf("%d%d%d",&u,&v,&w);
            u--;
            int p1 = getroot(u);
            int p2 = getroot(v);
            if(p1==p2){
                if(sum[v]-sum[u]!=w)res++;//更新答案
            }
            else{
                par[p2] = p1;
                sum[p2] = sum[u] - sum[v] + w;//自行画图即可得出该表达式
            }
        }
        printf("%d\n",res);
    }
    return 0;
}
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 归去来兮。 1.1 说明 本篇为《挑战程序设计竞赛(第2版)》[http://www.ituring.com.cn...
    尤汐Yogy阅读 14,909评论 0 160
  • 今天是时隔2年后比较正式得在企业上班,都市丽人,哈哈。其实没有间断的学习了解。比如去年一年的微商生涯,伴成长2个月...
    夏一墨阅读 1,293评论 0 0
  • 昨天晚上娃的数学作业错了好多题,今天早上起床后,我告诉娃,学习要踏实认真,不能粗心大意,慌慌张张地的。她听...
    橄榄绿_7e3a阅读 832评论 0 0
  • 已经很久没有在夜里醒来过了,时间有多长也已经记不得了。困到极致,常常是一秒入睡,不留半分踌躇。很多时候夜晚如同...
    风起时想你你阅读 1,059评论 0 0
  • 中国访问学者章莹颖在美期间遭遇绑架,至今下落(生死)不明。美国联邦调查局虽然抓到了嫌犯,无奈嫌犯只承认绑架,而不承...
    成观阅读 1,313评论 0 0