您的位置:首页 > 其它

Assign the task - HDU 3974 - 树 - 简单并查集

2017-06-01 17:45 387 查看

Assign the task - HDU 3974 - 树 - 简单并查集

题目:

  There is a company that has N employees(numbered from 1 to N),every employee in the company has a immediate boss (except for the leader of whole company).If you are the immediate boss of someone,that person is your subordinate, and all his subordinates are your subordinates as well. If you are nobody’s boss, then you have no subordinates,the employee who has no immediate boss is the leader of whole company.So it means the N employees form a tree.

  The company usually assigns some tasks to some employees to finish.When a task is assigned to someone,He/She will assigned it to all his/her subordinates.In other words,the person and all his/her subordinates received a task in the same time. Furthermore,whenever a employee received a task,he/she will stop the current task(if he/she has) and start the new one.

  Write a program that will help in figuring out some employee’s current task after the company assign some tasks to some employee.

Input


  The first line contains a single positive integer T( T <= 10 ), indicates the number of test cases.

  For each test case:

  The first line contains an integer N (N ≤ 50,000) , which is the number of the employees.

  The following N - 1 lines each contain two integers u and v, which means the employee v is the immediate boss of employee u(1<=u,v<=N).

  The next line contains an integer M (M ≤ 50,000).

  The following M lines each contain a message which is either

  ”C x” which means an inquiry for the current task of employee x

or

  ”T x y”which means the company assign task y to employee x.
(1<=x<=N,0<=y<=10^9)


Output


  For each test case, print the test case number (beginning with 1) in the first line and then for every inquiry, output the correspond answer per line.

Sample Input


1
5
4 3
3 2
1 3
5 2
5
C 3
T 2 1
C 3
T 3 2
C 3


Sample Output


Case #1:
-1
1
2


  题意:给你t组数据,每组数据给出n,然后n-1行描述两个点之间的从属关系,对于每组点
u v
有u的上级为v,然后是m行操作。
C x
代表查询x号员工正在做什么工作,
T x y
代表给x号员工分配任务y,当给一个员工分配任务的时候,他所有的下级都需要和他一起做这个工作。

  思路:这个题卡了我2天,2天啊!这道题被分在kuangbin专题的线段树里,可是网上线段树的题解我怎么也看不懂,无奈之下问了问学姐,结果学姐一语中的这个题最简单的思路。

  其实就是一个十分简化的并查集,用一个结构体存储每个员工得到编号为
number
的任务的时间
t
,然后在查询的时候,从这个员工向上搜索,记录下最晚得到的任务,就是这个人当前正在做的任务。

  这种写法我提交了一下,比线段树版本快一些。由此可见当思路被限制住的时候究竟有多可怕。既然有这么简单又高效的办法,我也就偷个懒不去研究线段树的写法了。

附上AC代码和注释:

//
//  main.cpp
//  L
//
//  Created by LucienShui on 2017/5/28.
//  Copyright © 2017年 LucienShui. All rights reserved.
//

#include <iostream>
#include <algorithm>
#include <set>
#include <string>
#include <vector>
#include <queue>
#include <map>
#include <stack>
#include <iomanip>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cctype>
#define memset(a,b,n) memset(a,b,n*sizeof(a[0]))
#define il inline
#define ll long long
#define ull unsigned long long

using namespace std;

#define ls (u<<1)
#define rs (u<<1|1)
#define lson u<<1,l,mid
#define rson u<<1|1,mid+1,r
const int maxn = 50010;

int pre[maxn];
struct {
int number,t;//在第t个时刻分配编号为number的任务给这个员工
}task[maxn];

int main ()
{
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
#endif // ONLINE_JUDGE
int t,n,m,u,v,Case,Time;
//测试样例组数,n个员工,m组关系
char c;
cin >> t;
for(int T = 1 ; T<=t ; T++) {
printf("Case #%d:\n",T);
scanf("%d",&n);
memset(pre,-1,n);
for(int i=1 ; i<n ; i++) {
task[i].number = task[i].t = -1;
//初始化1~n-1号员工的事件编号和得到这个任务的时间为-1
scanf("%d%d",&u,&v);
pre[u]=v;
}
task
.number = task
.t = -1;//初始化第n个员工的事件编号和得到这个任务的时间为-1
cin >> m;
for(int i=1 ; i<=m ; i++) {
scanf(" %c",&c);
if(c=='C') {
scanf("%d",&u);
Time = Case = -1;//当前任务Case对应的得到时间Time
while(~u) {//得到从这个员工到他的最高级领导所经过的路径中最晚得到的任务编号
if(Time < task[u].t) {
Case = task[u].number;
Time = task[u].t;
}
u = pre[u];
}
printf("%d\n",Case);//输出这个事件,默认为-1
}
else {
scanf("%d%d",&u,&v);
//u号员工在第i时间得到任务v
task[u].number = v;
task[u].t = i;
}
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息