HDU 3047 排座位(带权值的并查集)

先上代码

 

#include<stdio.h>
int set[50005];
int dist[50005];
int count;
 int find(int a)
{
    if(set[a]==a)return a;

    int tem = set[a];
    set[a]=find( set[a]);
    dist[a] += dist[tem ];
    return set[a];
}
void merge(int x,int y,int s)
{
    int fx=find(x);
    int fy=find(y);
    if(fx!=fy)
    {
        set[fy]=fx;
        dist[fy]=dist[x]+s-dist[y];
    }
    else
    {
        if(dist[y]-dist[x]!=s)
        count++;
    }
}
int main()
{
    int n,m,a,b,c,i;
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        count=0;
        //初始化
        for(i=1;i<=n;i++)
        {
            set[i]=i;
            dist[i]=0;
        }
        for(i=1;i<=m;i++)
        {
            scanf("%d%d%d",&a,&b,&c);
            merge(a,b,c);
        }
        printf("%d\n",count);
    }
    return 0;
}

思路不难,两个数字,一个set数组,里面的元素代表他的参照座位是谁,一个dist数组,元素大小表示它距离参照座位的距离,一开始初始化,set[1]=1;dist[1]=0,依次初始化,接着输入关系,根据A B X 建立相互之间的关系。

 

首先进入merge函数,但是真正运行的还是find函数,find函数两个作用,一是让传入的座位的set值直接变为一个最终标准的参照座位,在一个相互之间存在关系范围内有一个唯一的标准座位,例如北京时间;然后dist也跟着递归的进行不断的调整,最后为距离参照座位的距离。

 接着根据find返回的最终参照座位进行判定,如果俩个座位的标准参照座位相等,则表示这两个座位在一个关系范围内,也就是两个座位早就已经有了确切的位置(相对于同一个标准座位),但是此次给他们的关系说明不对,

 

if(dist[y]-dist[x]!=s)
        count++;

与原始矛盾,则这就是一个错误了。

 

如果两个座位的标准参照座位不同,那说明他们各自原来处于的关系范围互不相干,他们之间都没有确切的位置关系,所以这个时候肯定没有错误,因为 A B早就没有设定关系,我们可以通过移动他们之中的一个标准座位的位置来满足这个所给的关系,但是之后,他们两个关系范围内的所有座位彼此之间就有了确切的约束了。

如图一样,A C 之间有确定关系,B D之间也有,但是A与 B或者D之间没关系,也就是没限制,但是一旦给了一个条件,四人关系就确定下来了。

注意,相对于同一个列,不同元素重复了无所谓,因为可以做外圈,只要保证列之间的关系即可,也就是无限座位,而且题目所给300的约束条件都是虚假的。满了可以另起一圈。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值