[Swust OJ 1091]--土豪我们做朋友吧(并查集,最值维护)

 

题目链接:http://acm.swust.edu.cn/problem/1091/

 

Time limit(ms): 1000      Memory limit(kb): 32768
 

人都有缺钱的时候,缺钱的时候要是有个朋友肯帮助你,那将是一件非常幸福的事情。有N个人(编号为1到N),一开始他们互相都不认识,后来发生了M件事情,事情分为2个种类,1:A和B成为了朋友,并且A的所有朋友都成了B的朋友,B的所有朋友也都成了A的朋友。2:A缺钱了,请求帮助,他需要向他朋友中钱最多的请求帮助,若不止一位,选择编号最小的。

Description

多组测试数据,每组第一行是整数N(2<=N<=100000),表示有N个人,第二行N个数据,依次表示每个人有多少钱,第三行是M(1<=M<=100000),表示发生了M个事件。接下来是M行,首先输入事件种类P(1或者2),然后是对应的两个或者一个整数A,B或者A。数据保证都在32位以内。

Input

对于每一个事件2,输出A需要请求的人的编号,若没有人能够帮助他,输出"NO ONE CAN HELP!"。

Output
1
2
3
4
5
6
7
3
1 2 3
3
2 1
1 1 3
2 1
 
Sample Input
1
2
3
NO ONE CAN HELP!
3
 
Sample Output
输出换行请使用\r\n
 
解题思路:直接的一个并查集能过所有的数据,但是数据量过大,单纯的并查集会直接超时;
     那么在使用并查集将最大与次大元素找出,然后维护就可以了
(之所以找最大和次大,在并查集合并过程中初始化最大元素为自己,恩,你懂得~~)
代码如下:
 1 #include<iostream>
 2 #include<cstdlib>
 3 #include<cstring>
 4 using namespace std;
 5 int n, m, a, b, c, f[100001], val[100001];
 6 struct tuhao{
 7     int pos, money;
 8 };
 9 struct node{
10     tuhao max[4];
11 }x[100001];
12 int cmp(const void *x, const void *y){
13     if ((*(tuhao *)x).money == (*(tuhao *)y).money)
14         return (*(tuhao *)x).pos - (*(tuhao *)y).pos;
15     return (*(tuhao *)y).money - (*(tuhao *)x).money;
16 }
17 void init(){
18     memset(x, 0, sizeof(x));
19     for (int i = 1; i <= n; i++){
20         x[i].max[0].money = val[i];
21         x[i].max[0].pos = f[i] = i;
22  
23     }
24 }
25 int findset(int k){
26     int i = k, j = k, r;
27     while (i != f[i])
28         i = f[i];
29     while (j != i){
30         r = f[j];
31         f[j] = i;
32         j = r;
33     }
34     return i;
35 }
36 void mergy(int a, int b){
37     int tx = findset(a), ty = findset(b), i;
38     if (tx != ty){
39         f[ty] = tx;
40         for (i = 2; i < 4; i++){
41             x[tx].max[i].pos = x[ty].max[i - 2].pos;
42             x[tx].max[i].money = x[ty].max[i - 2].money;
43         }
44         qsort(x[tx].max, 4, sizeof(x[tx].max[0]), cmp);
45         for (i = 2; i < 4; i++)
46             x[tx].max[i].pos = x[tx].max[i].money = 0;
47     }
48 }
49 void Search(int k){
50     int v = findset(k);
51     if (!x[v].max[1].pos)
52         cout << "NO ONE CAN HELP!\r\n";
53     else
54         cout << (x[v].max[0].pos == k ? x[v].max[1].pos : x[v].max[0].pos) << "\r\n";
55 }
56 int main(){
57     while (cin >> n){
58         for (int i = 1; i <= n; i++)
59             cin >> val[i];
60         init();
61         cin >> m;
62         for (int i = 0; i < m; i++){
63             cin >> a;
64             switch (a){
65             case 1:cin >> b >> c; mergy(b, c); break;
66             default:cin >> b; Search(b); break;
67             }
68         }
69     }
70     return 0;
71 }
View Code

 

posted @ 2015-06-14 10:43  繁夜  阅读(496)  评论(5编辑  收藏  举报