How many answers are wrong(并查集)

刚开始看可能Jio着这道题和并查集没有什么关系,不过仔细观察可以发现既然要判断矛盾就肯定知道与以前的数据有冲突的地方,因为没有说这个数列是不是正整数所以冲突的方式只有一种,比如先说了连个区间
1-10 10
1-5 2
6-10 5
跟明显第三句话就可以看出来问题了,第二个加第三个跟第一个不相等,但是他们表述的区间都是相同的,所以产生矛盾,不过这种矛盾应该怎么判断呢,我们可以以它的端点为点建立一个集合,他们的根就是能到达的最左端,如果都有相同的最左端那么就可以判断一下是否有矛盾产生。

假设两个端点的是A和B,A到B是W;那么B-(A-1)=W;所以这道题就有了并查集的意味

#include <iostream>

using namespace std;
const int maxn=200010;
int pre[maxn],val[maxn];
int find(int x)
{
    int k=pre[x];
    if(pre[x]!=x)
    {
        pre[x]=find(pre[x]);
        val[x]+=val[k];
    }
    return pre[x];
}

int main()
{
    int N,M;
    while(cin>>N>>M)
    {
        int i,u,v,w,ans=0;
        for(i=0;i<=N;i++)//第一步初始化
        {
            pre[i]=i;
            val[i]=0;
        }
        while(M--)
        {
            cin>>u>>v>>w;
            u=u-1;
            /**********Union函数写道主函数里*************/
            int ru=find(u);
            int rv=find(v);
            if(ru==rv&&val[u]+w!=val[v])
                ans++;
            else if(ru<rv)
            {
                pre[rv]=ru;
                val[rv]=val[u]-val[v]+w;
            }
            else if(ru>rv)
            {
                pre[ru]=rv;
                val[ru]=val[v]-val[u]-w;
            }
        }
        cout<<ans<<endl;
    }
    //cout << "Hello world!" << endl;
    return 0;
}

猜你喜欢

转载自blog.csdn.net/guagua_de_xiaohai/article/details/80787099