【海岛帝国系列赛】No.3 海岛帝国:运输资源
海岛帝国:运输资源
【试题描述】
YSF考虑到“药师傅”帝国现在资源极度不平均,于是,商讨启用南水北调工程。YZM为首席工程师。现在,YSF由于工作紧张,准备军用物资和民用物资。但他要时时关注运输工程动态,因为货物很珍贵,是最新发明的T-2500智能生产行业制造机。用于工、农业生产,而且技术先进,数量众多,不能落入恐怖分子之手。YSF要YZM向他随时汇报货物走向、货物地点,以防万一恐怖分子袭击。脾气暴躁的YZM一向不爱干这种统筹规划的杂活。所以,YZM需要你来帮他编一个小程序,来随时给多疑的YSF汇报。(程序当然是有薪水的,至于多少嘛……可以找YSF,LJX面谈)
【输入要求】
* 第一行:两个数n,m,表示一共有n个制造机,m条操作。操作有两种。
* 接下来的m行:T a b 表示把a制造机所在的城里的所有龙珠运到b所在的城里
Q a 表示对a的询问,要求输出x a所在的城, y a所在的城里一共有多少个机器,z a经过几次到达现在所在的城的。
【输出要求】
* 及每次Q查询的答案,回车!回车!回车!
【输入实例】
3 4
Q 1
T 3 2
Q 2
Q 3
【输出实例】
1 1 0
2 2 0
2 2 1
【其他说明】
所有数据不大于40
【试题分析】
第一眼上来就看到合并,查询等一些操作字符了,第一反应貌似是线段树?可惜,如果一上来这么分析,而不考虑麻烦程度的话,那我也就没话可说了。线段树操作这题貌似是能解决,但是本人不怎么会线段树,所以我就又蒙了个模拟线段树的并查集算法?呵呵呵。因为我想都是树形结构。所以就套了一发,其实本来就是一样的啊。定义parent同并查集的一般操作,step表示经过几步到达现在所在的城,size表示该城里的龙珠数。上回讲解并查集时提到了其它多种操作:Union。具体代码如下:
1 void Union(int a,int b) 2 { 3 int pa=find(a); 4 int pb=find(b); 5 par[pa]=pb; 6 size[pb]+=size[pa]; 7 step[pa]++; 8 }
当然,定义初值要按题意定义:
1 void init(int n) 2 { 3 for(int i=1;i<=n;i++) 4 { 5 par[i]=i; 6 step[i]=0; 7 size[i]=1; 8 } 9 } 10
【代码如下】
1 #include <cstdio> 2 #include <cstring> 3 using namespace std; 4 #define MAX 10 5 int par[MAX],step[MAX],size[MAX]; 6 void init(int n) 7 { 8 for(int i=1;i<=n;i++) 9 { 10 par[i]=i; 11 step[i]=0; 12 size[i]=1; 13 } 14 } 15 16 int find(int x) 17 { 18 if(x==par[x]) return x; 19 int tmp=par[x]; 20 par[x]=find(tmp); 21 step[x]+=step[tmp]; 22 return par[x]; 23 } 24 25 void Union(int a,int b) 26 { 27 int pa=find(a); 28 int pb=find(b); 29 par[pa]=pb; 30 size[pb]+=size[pa]; 31 step[pa]++; 32 } 33 34 int main() 35 { 36 int T,n,m,a,b,t=1; 37 scanf("%d%d",&n,&m); 38 init(n); 39 for(int i=0;i<m;i++) 40 { 41 char move; 42 getchar(); 43 move=getchar(); 44 if(move=='T') 45 { 46 scanf("%d%d",&a,&b); 47 Union(a,b); 48 } 49 else 50 { 51 scanf("%d",&a); 52 int pa=find(a); 53 printf("%d %d %d\n",pa,size[pa],step[a]); 54 } 55 } 56 }