HDU 3038 How Many Answers Are Wrong(带权并查集)

太坑人了啊,读入数据a,b,s的时候,我刚开始s用的%lld,给我WA。 实在找不到错误啊,后来不知怎么地突然有个想法,改成%I64d,竟然AC了

思路:我建立一个sum数组,设i的父亲为fa,sum[i]表示(fa,i]中的数的和(不包括fa,包括i),    

  合并的时候,不是合并a,b,而是合并a-1,b。这样做的目是因为s是[a,b]的和,如果直接合并a,b,那么按照我数组的定义应该是(a,b]的和,这样不符合题意。    

  接下来,每次读入a,b,只要根据他们父节点的不同情况分类讨论即可。

 

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;

const int maxn=200010;
int father[maxn];
long long sum[maxn]; //设i的父亲为fa,sum[i]表示(fa,i]中的数的和(不包括fa,包括i)
int n,m;
void init() {
    for(int i=0; i<=n; i++) {
        father[i]=i;
        sum[i]=0;
    }
}

int find_root(int x) {
    if(father[x]==x)
        return x;
    int fa=father[x];
    father[x]=find_root(father[x]);
    sum[x]=(sum[x]+sum[fa]);
    return father[x];
}
//合并的时候,保证x<y
void Union(int x,int y) {
    father[y]=x;
}
int main() {
    int a,b,ans=0;
    long long s;
    while(scanf("%d%d",&n,&m)!=EOF) {
        init(); //怎么老忘记写这个啊
        ans=0;
        for(int i=1; i<=m; i++) {
            scanf("%d%d%I64d",&a,&b,&s);   //就是这里,本来用的是lld的格式,导致WA
            int fa=find_root(a-1);
            int fb=find_root(b);
            /*
            fa=fb时,(fa,a-1]=sum[a-1],(fb,b]=sum[b],
                     ——>[a,b]=sum[b]-sum[a-1],显然即应该等于s
                     若不等于,即使错误的
            */
            if(fa==fb) {
                if(sum[b]-sum[a-1]!=s) {
                    ans++;
                }
            }
            else {
                if(fb>a-1) {
                    /*
                    大小关系:fa<=a-1<fb<=b
                    (fa,a-1]=sum[a-1],[a,b]=s,(fb,b]=sum[b];
                    ——>[a,fb]=s-sum[b],
                       (fa,fb]=(fa,a-1]+[a-1,fb]=sum[a-1]+s-sum[b];
                    */
                    Union(fa,fb);
                    //更新fb的父节点fa到fb区间的和(不包括fa)
                    sum[fb]=sum[a-1]+s-sum[b];
                } else if(fb==a-1) {
                    /*
                    大小关系:fa<=a-1=fb<=b
                    (fa,a-1]=sum[a-1],[a,b]=s,(fb,b]=sum[b];
                     ——>sum[b]即为[a,b]的和。
                     若sum[b]不等于s,说明错误
                     如果相同,则合并
                    */
                    if(s!=sum[b]) {
                        ans++;
                    } else {
                        Union(fa,fb);
                        sum[fb]=sum[a-1];
                    }
                }
                //fb<a-1
                else {
                    if(fb>fa) {
                    /*
                    大小关系:fa<fb<a-1<b
                    (fb,b]=sum[b],(a-1,b]=s ——>(fb,a-1]=sum[b]-s;
                    再由(fa,a-1]=sum[a-1]——>(fa,fb]=sum[a-1]-sum[b]+s;
                    */
                        Union(fa,fb);
                        sum[fb]=sum[a-1]-sum[b]+s;
                    }
                    else {
                    /*
                    大小关系:fb<fa<=a-1<=b
                    (fb,b]=sum[b],(a-1,b]=s,(fa,a-1]=sum[a-1];
                     ——>(fa,b]=s+sum[a-1]
                     ——>(fb,fa]=sum[b]-s-sum[a-1];
                    */
                        Union(fb,fa);
                        sum[fa]=sum[b]-s-sum[a-1];
                    }

                }
            }
        }
        printf("%d\n",ans);
    }
    return 0;
}

 

posted @ 2013-09-02 20:25  辰曦~文若  阅读(163)  评论(0编辑  收藏  举报