合作网络

合作网络D306

运行时间限制:1000ms; 运行空间限制:51200KB

试题描述

有n个结点,初始时每个结点的父结点都不存在。你的任务是执行若干次Set操作和Query操作,格式如下:
    Set u v:把结点u的父结点设为v,距离为|u-v|除以1000的余数。输入保证执行指令前u没有父结点。
    Query u:询问u到根结点的距离。

输入

第一行包含两个正整数n和m,表示共有n个结点(编号从1到n),m条指令。接下来的m行每行包含一个指令,其中Set指令的个数小于n。

输出

若干行,各行依次对应每一个查询指令的查询结果。

输入示例

20 10
Set 2 4
Set 6 9
Set 4 8
Set 5 9
Query 2
Query 4
Set 13 8
Set 11 12
Set 3 9
Query 3

输出示例

6
4
6

其他说明

数据范围:0<m<10000,m<n,0<n,u,v<20000。

UVA3027

---------------------------------------------------------------------------------------------------------------------------------

讲解:

刚会了并查集的朋友看到这道题可能有些束手无策,其实这道题的本质就是在压缩路径时顺带压缩到根的距离。

代码实现(结构体实现略):

#include<iostream>

#include<cstdio>

#include<cstring>

#include<algorithm>

#include<cmath>

using namespace std;

int a[20010][2];

int gets(int t)

{

         int k=a[t][0];

         if(a[t][0]==t) return t;

         a[t][0]=gets(a[t][0]);

         a[t][1]+=a[k][1];

         return a[t][0];

}

int main()

{

    int i,t1,t2,n,m;

         char str[5];

         scanf("%d%d",&n,&m);

         for(i=1;i<=m;i++)

         {

             scanf("%s",&str);

                   if(str[0]=='Q')

                   {

                            scanf("%d",&t1);

                            gets(t1);

                            cout<<a[t1][1]%1000<<endl;

                   }       

                   else

                   {

                            scanf("%d%d",&t1,&t2);

                            a[t1][0]=t2;

                            a[t1][1]=abs(t1-t2);

                   }

         }

         return 0;

}
View Code
posted @ 2018-02-12 09:49  欢语_暗影  阅读(155)  评论(0)    收藏  举报