您的位置:首页 > 其它

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

2017-08-30 16:18 267 查看
先上代码

#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的约束条件都是虚假的。满了可以另起一圈。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: