图算法11之1023

1 题目编号:1023

2 题目内容:

Problem Description
In 12th Zhejiang College Students Games 2007, there was a new stadium built in Zhejiang Normal University. It was a modern stadium which could hold thousands of people. The audience Seats made a circle. The total number of columns were 300 numbered 1--300, counted clockwise, we assume the number of rows were infinite.<br>These days, Busoniya want to hold a large-scale theatrical performance in this stadium. There will be N people go there numbered 1--N. Busoniya has Reserved several seats. To make it funny, he makes M requests for these seats: A B X, which means people numbered B must seat clockwise X distance from people numbered A. For example: A is in column 4th and X is 2, then B must in column 6th (6=4+2).<br>Now your task is to judge weather the request is correct or not. The rule of your judgement is easy: when a new request has conflicts against the foregoing ones then we define it as incorrect, otherwise it is correct. Please find out all the incorrect requests and count them as R.<br>
 

Input
There are many test cases:<br>For every case: <br>The first line has two integer N(1<=N<=50,000), M(0<=M<=100,000),separated by a space.<br>Then M lines follow, each line has 3 integer A(1<=A<=N), B(1<=B<=N), X(0<=X<300) (A!=B), separated by a space.<br><br>
 

Output
For every case: <br>Output R, represents the number of incorrect request.<br>
 

Sample Input
  
  
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
 

Sample Output
  
  
2

3 解题思路形成过程:这是一道并查集题目。
(1)弄清题意,找出出现冲突的位置,判断冲突很简单就是当两个人在同一行坐,同时他们到根节点的距离差值正好是他们之间的差值,此时就出现了冲突了。
(2)关键有两个地方,这也是并查集题目的难点,就是压缩集合,和求节点到根的距离。这里压缩集合就很简单了,一个通用的递归。求到跟的距离dist[a] += dist[tem]; dist[rb]=dist[a]+x-dist[b];这两行代码是核心代码,第一行是求出节点a到根的距离。

4 代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define MAXNUM 50005

using namespace std;
//father:存储的是节点的父节点的下标,dist存储的是相对于父节点的距离
int father[MAXNUM],dist[MAXNUM];
int n,m;

int find_father(int a)
{
    if(father[a]==a)return a;
    int tem = father[a];
    father[a]=find_father(father[a]);
    dist[a] += dist[tem];
    return father[a];
}

void union_set(int a,int b,int x)
{
    int ra = find_father(a);
    int rb = find_father(b);
    father[rb]=ra;
    dist[rb]=dist[a]+x-dist[b];
}
int main()
{
    int a,b,ra,rb,x,conflics;
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        memset(dist,0,sizeof(dist));
        for(int i=0;i<=n;i++)
        father[i]=i;
        conflics=0;
        for(int i=0;i<m;i++)
        {
            scanf("%d%d%d",&a,&b,&x);
            ra = find_father(a);
            rb = find_father(b);
            if(ra==rb)
            {
                if(dist[b]-dist[a]!=x)conflics++;
            }
            if(ra!=rb)union_set(a,b,x);
        }
        printf("%d\n",conflics);
    }
    return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值