Hdoj 3047 Zjnu Stadium

本文深入解析并查集的应用场景,通过解决冲突问题,掌握并查集的压缩集合和求节点到根距离的核心算法。利用数学中的向量计算原理,巧妙地求出节点间的实际距离,避免冲突发生。

题目传送门

//求解本题需要弄清楚冲突发生的条件,很容易看出此题为种类并查集的变种,题上提到了距离,自然想到是带权值的并查集,关键是这个权值怎么办。
//菜鸟参考网上各位大牛的解法终于懂了这道题的前因后果。有必要将解题过程中的心得体会记录下来。
//(1)弄清题意,找出出现冲突的位置,判断冲突很简单就是当两个人在同一行坐,同时他们到根节点的距离差值正好是他们之间的差值,此时就出现了冲突了。(本质就是两个人到了同样的位置)
//(2)关键有两个地方,这也是并查集题目的难点,就是压缩集合,和求节点到根的距离。这里压缩集合就很简单了,一个通用的递归。求到根的距离:   dist[a]+= dist[tem]; 
dist[rb]=dist[a]+x-dist[b];
//注意这两行代码,这是核心代码,首先第一行是求出节点a到根的距离。第二行代码使用的是数学中向量计算的原理如图
![图片](https://img-blog.youkuaiyun.com/20160115202251039)

//Created Author: just_sort
//Created Time  : 2016/1/15 19:59
//File Name     : Zjtu Stadium
#pragma comment(linker, "/STACK:102400000,102400000")
#include <cstdio>
#include <cstring>
#include <cctype>
#include <iostream>
using namespace std;
const int maxn=50010;
int fa[maxn],dis[maxn];

void init()
{
    for(int i=0;i<maxn;i++)
    {
        fa[i]=i;
        dis[i]=0;
    }
}
int Find(int x)
{
    if(x==fa[x])return x;
    int fx=fa[x];
    fa[x]=Find(fa[x]);
    dis[x]+=dis[fx];//节点x到根的距离
    return fa[x];
}
void union_set(int u,int v,int x)
{
    int fx = Find(u);
    int fy = Find(v);
    fa[fy]=fx;
    dis[fy]=dis[u]-dis[v]+x;//数学中距离的计算(向量法)
}
int main()
{
    int n,m,ans;
    int u,v,w;
    while(~scanf("%d%d",&n,&m))
    {
        init();
        ans=0;
        for(int i=1; i<=m; i++)
        {
            scanf("%d%d%d",&u,&v,&w);
            if(Find(u)!=Find(v))union_set(u,v,w);
            else if(dis[u]+w!=dis[v])ans++;
        }
        printf("%d\n",ans);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值