HDU 3038How Many Answers Are Wrong

来源:互联网 发布:c语言线程同算法 编辑:程序博客网 时间:2024/06/17 00:45

题目链接
题意:给你N个数和M次询问,每次询问包含三个数a、b、c,表示区间[a,b](包括a、b)的总和是c,前提是当后面的询问与前面的询问出现矛盾时,忽略此次询问,表示出错数+1,问在M次询问中出错数是多少。
题目解析:并查集。设置两个数组parent与data,分别表示某个数的根与到此根的距离(即根与此数区间的和),当两个数根不同时,合并两个数,把大根并到小根上,并更新data。[a,b]可以理解为b到根的距离-(a-1)到根的距离,前提是a、b根相同。

#include <iostream>#include <cstdio>#include <fstream>#include <algorithm>#include <cmath>#include <deque>#include <vector>#include <queue>#include <string>#include <cstring>#include <map>#include <stack>#include <set>#include <climits>using namespace std;const int MAXN=2*1e5+10;int parent[MAXN], data[MAXN];int N, M, sum;void start(){    for(int i=0; i<=N; i++)        parent[i]=i;    memset(data,0,sizeof(data));    sum=0;}int Find(int a){    if(parent[a]==a)return a;    int b=parent[a];    parent[a]=Find(parent[a]);    data[a]+=data[b];///在寻找a的根节点的同时,不断更新data值    return parent[a];}void add(int a, int b, int c, int d, int e)///画图解决,更易理解{    if(a<b)    {        parent[b]=a;        data[b]=data[c]+e-data[d];    }    else    {        parent[a]=b;        data[a]=data[d]-e-data[c];    }}int main(){    while(cin>>N>>M)    {        int a, b, c;        start();        while(M--)        {            cin>>a>>b>>c;            a--;            int d=Find(a);            int e=Find(b);            if(d!=e)///根不同则合并                add(d,e,a,b,c);            else///相同则检验是否矛盾            {                if(data[b]!=data[a]+c)                    sum++;            }        }        cout<<sum<<endl;    }    return 0;}