[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 }
如果这是你所爱的,就不要让自己后悔~~~