我现在做的是第四专题编号为1023的试题,具体内容如下所示:
Problem W
Time Limit : 2000/1000ms (Java/Other) Memory Limit : 32768/32768K (Java/Other)
Total Submission(s) : 20 Accepted Submission(s) : 8
10 10 1 2 150 3 4 200 1 5 270 2 6 200 6 5 80 4 7 150 8 9 100 4 8 50 1 7 100 9 2 100
2
简单题意:
有一个体育馆,座位呈环状,想象下,貌似体育馆都是这样的,每一列有300个座位,按逆时钟方向编号为1~300,假设行数无穷大。
某一天,有N个人(编号为1~N)来到这个体育馆看一场赛事,主办方提出了M个要求,要求的格式是"A B X",表示的是,假设A坐在编号为i的列,则B必须坐在编号为(i+x)的列上,这些要求里有一些是错误的,只有和前面的要求产生冲突时才算错误,其它都是正确的。程序要输出错误的要求个数。
解题思路:
这是一道比较简单地并查集题目。
(1)弄清题意,找出出现冲突的位置,判断冲突很简单就是当两个人在同一行坐,同时他们到根节点的距离差值正好是他们之间的差值,此时就出现了冲突了。
(2)关键有两个地方,这也是并查集题目的难点,就是压缩集合,和求节点到根的距离。这里压缩集合就很简单了,一个通用的递归。求到跟的距离dist[a]+= dist[tem];dist[rb]=dist[a]+x-dist[b];注意这两行代码,这是核心代码,首先第一行是求出节点a到根的距离。
编写代码:
#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;
while(scanf("%d%d",&n,&m)!=EOF)
{
count=0;
for(int i=2;i<=n;i++)
{
set[i]=i;
dist[i]=0;
}
for(int i=1;i<=m;i++)
{
scanf("%d%d%d",&a,&b,&c);
merge(a,b,c);
}
printf("%d\n",count);
}
return 0;
}