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

题目链接:https://vjudge.net/problem/HDU-3038#author=jack10086
转自:https://blog.csdn.net/weixin_44224825/article/details/104241108
题意:给多个区间以及区间和,假设前面的推论是正确的,求有多少矛盾的推论。区间和不能为负数。例如1-10=100,1-5=200就是矛盾的。
思路:pa[i]表示和i有关系的最左端的点,设为根节点,dis[i]表示i距离pa[i]的距离。每次输入区间a,b时,如果两个数的根节点x,y相同,说明是有相同的参照数,因此可以计算两点间的距离。如果不相同,说明没有相同的标准,因此不能计算,但是有了d,a与b所在的集合可以建立关系。合并两个数所在的集合,注意x和y的大小关系。
这里的a–是为了特判6 6 1此类的数据的情况。 一般区间类题目都会这样操作。
并查集修改距离时,应该先按照距离根节点位置从小到大修改,也就是说dis的修改不能在pa修改之前。例如1<-2<-3<-4,在一开始,pa[3]=2,pa[4]=3,此时dis[3]记录的是2与3间的距离,如果先修改dis[4],就会出错。

#include<algorithm>
#include<iostream>
#include<cstring>
#include<string>
#include<cstdio>
#include<vector>
#include<stack>
#include<cmath>
#include<queue>
#include<set>
#include<map>
using namespace std;
const int maxn=2e5+5;
int pa[maxn],dis[maxn];
int fnd(int x)
{
    if(pa[x]==x)
        return x;
    int pre=pa[x];
    pa[x]=fnd(pa[x]);
    dis[x]+=dis[pre];
    return pa[x];
}
int main()
{
    int n,m;
    while(~scanf("%d%d",&n,&m))
    {
        memset(dis,0,sizeof(dis));
        for(int i=1; i<=n; i++)
        {
            pa[i]=i;
        }
        int a,b,d;
        int ans=0;
        for(int i=0; i<m; i++)
        {
            scanf("%d%d%d",&a,&b,&d);
            a--;
            int x=fnd(a),y=fnd(b);
            if(x!=y)
            {
                if(y>x)
                {
                    pa[y]=x;
                    dis[y]=dis[a]+d-dis[b];
                }
                else
                {
                    pa[x]=y;
                    dis[x]=dis[b]-dis[a]-d;
                }
            }
            else
            {
                if(dis[a]+d!=dis[b])
                {
                    ans++;
                }
            }
        }
        printf("%d\n",ans);
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,以下是代码形式的电话线路图状态: ``` @startuml title Telephone State Diagram [*] --> Idle : Initial State Idle --> Dialing : Off Hook Event Dialing --> Connecting : Valid Number Event Dialing --> Disconnected : Invalid/Wrong Number Event Connecting --> TimeOut : Timeout Event Connecting --> Connected : Called Phone Answers Event Ringing --> Connected : Called Phone Answers Event Connected --> Idle : On Hook Event Connected --> Busy Tone : Line Busy Event Connected --> TimeOut : Timeout Event Connected --> Disconnected : Timeout Event Connected --> Ringing : Play Message Event @enduml ``` 解释一下: - 初始状态为空闲状态(`[*] --> Idle : Initial State`)。 - 当电话机摘机时,电话状态从空闲状态转入拨号状态(`Idle --> Dialing : Off Hook Event`)。 - 当拨号有效号码时,电话状态从拨号状态转入连接状态(`Dialing --> Connecting : Valid Number Event`)。 - 当拨号号码无效或错误时,电话状态从拨号状态转入未连接状态(`Dialing --> Disconnected : Invalid/Wrong Number Event`)。 - 当连接超时时,电话连接状态从连接状态转入超时状态(`Connecting --> TimeOut : Timeout Event`)。 - 当被拨打的电话接听时,电话连接状态从连接状态或响铃状态转入已连接状态(`Connecting --> Connected : Called Phone Answers Event` 或 `Ringing --> Connected : Called Phone Answers Event`)。 - 当已连接状态的电话机挂机时,电话状态从已连接状态转入空闲状态(`Connected --> Idle : On Hook Event`)。 - 当已连接状态的电话线路忙碌时,电话状态从已连接状态转入忙音状态(`Connected --> Busy Tone : Line Busy Event`)。 - 当已连接状态的电话连接超时时,电话状态从已连接状态转入未连接状态(`Connected --> TimeOut : Timeout Event`)。 - 当已连接状态的电话播放信息时,电话状态从已连接状态转入响铃状态(`Connected --> Ringing : Play Message Event`)。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值