Tsinsen-A1491 家族【并查集】
问题描述
阿狸和桃子养了n个小阿狸, 小阿狸们每天都在一起玩的很开心. 作为工程师的阿狸在对小阿狸们之间的关系进行研究以后发现了小阿狸的人际关系由某种神奇的相互作用决定, 阿狸称之为“键”. 每个键有一个频率, 称为键频率, 是一个整数(单位Hz).
由于小阿狸们每天成集团地黏在一起, 桃子希望他们能够分成更加独立的几团. 阿狸发现, 一旦小阿狸们分开, 独立的一块连在一起的几个小阿狸就会形成一个家族, 而家族的类型由这个家族的小阿狸的数量唯一确定(比如说只有一个小阿狸的家族显然就是单身码农, 两个小阿狸的显然是一对小阿狸恋人, 三个小阿狸的就是三口之家等等). 显然, 一个小阿狸和另一个小阿狸处于同一家族, 当且仅当两个小阿狸之间存在直接或间接的键组成的路径.
桃子对每种小阿狸家族都有自己的喜好程度, 她希望所有的小阿狸家族喜好程度之和大于等于K.
为了让小阿狸们分开来, 阿狸决定让某些键断裂, 只保留某一段频率的键, 比如说100Hz到140Hz频率的键, 这时频段宽度为40Hz. 当然, 阿狸希望频段宽度越小越好, 但至少要有一个小键. 你的任务就是求出最小的频段宽度.
注意, 输入不保证全部键都有效时只有一个小阿狸家族.
由于小阿狸们每天成集团地黏在一起, 桃子希望他们能够分成更加独立的几团. 阿狸发现, 一旦小阿狸们分开, 独立的一块连在一起的几个小阿狸就会形成一个家族, 而家族的类型由这个家族的小阿狸的数量唯一确定(比如说只有一个小阿狸的家族显然就是单身码农, 两个小阿狸的显然是一对小阿狸恋人, 三个小阿狸的就是三口之家等等). 显然, 一个小阿狸和另一个小阿狸处于同一家族, 当且仅当两个小阿狸之间存在直接或间接的键组成的路径.
桃子对每种小阿狸家族都有自己的喜好程度, 她希望所有的小阿狸家族喜好程度之和大于等于K.
为了让小阿狸们分开来, 阿狸决定让某些键断裂, 只保留某一段频率的键, 比如说100Hz到140Hz频率的键, 这时频段宽度为40Hz. 当然, 阿狸希望频段宽度越小越好, 但至少要有一个小键. 你的任务就是求出最小的频段宽度.
注意, 输入不保证全部键都有效时只有一个小阿狸家族.
输入格式
第一行3个整数n(<=1000), m(<=5000), K(0~2^31-1).
接下来1行n个整数, 第k的整数表示桃子对大小为k的小阿狸家族的喜爱程度.
接下来m行, 每行3个整数, u, v, f. 表示u小阿狸和小阿狸v之间存键, 频率f Hz.
接下来1行n个整数, 第k的整数表示桃子对大小为k的小阿狸家族的喜爱程度.
接下来m行, 每行3个整数, u, v, f. 表示u小阿狸和小阿狸v之间存键, 频率f Hz.
输出格式
一个整数, 即最窄的频段宽度(不存在可行频段, 输出"T_T", 不含引号).
样例输入
4 4 52
1 50 2 9
1 2 6
2 3 8
3 4 4
1 4 3
1 50 2 9
1 2 6
2 3 8
3 4 4
1 4 3
样例输出
0
样例说明
频段3Hz~3Hz或4Hz~4Hz或6Hz~6Hz或8Hz~8Hz
样例输入
4 4 10
1 5 2 9
1 2 6
2 3 8
3 4 4
1 4 3
1 5 2 9
1 2 6
2 3 8
3 4 4
1 4 3
样例输出
2
样例说明
频段4Hz~6Hz
样例输入
4 4 10
1 4 2 9
1 2 6
2 3 8
3 4 4
1 4 3
1 4 2 9
1 2 6
2 3 8
3 4 4
1 4 3
样例输出
T_T
数据规模和约定
对于 30% 的数据, n <=10
对于 50% 的数据, n <=50 , m <=200
对于 100% 的数据, n <=1000 , m <=3000
对于 50% 的数据, n <=50 , m <=200
对于 100% 的数据, n <=1000 , m <=3000
题解
首先m<=5000,看不到这个就世界再见。
一开始是肯定是把边排序,然后来枚举,我一开始是这样写的,两个两个,三个三个,四个四个枚举,然后就退化成n^3方了。
Ngshily大爷讲了题解,我们在确定起点的情况下,依次把终点向后移动,每次考虑新加入的边造成的家族的影响,然后就是n^2了。
View Code
1 #include <bits/stdc++.h> 2 #define rep(i, a, b) for (int i = a; i <= b; i++) 3 #define drep(i, a, b) for (int i = a; i >= b; i--) 4 #define REP(i, a, b) for (int i = a; i < b; i++) 5 #define mp make_pair 6 #define pb push_back 7 #define clr(x) memset(x, 0, sizeof(x)) 8 #define xx first 9 #define yy second 10 using namespace std; 11 typedef long long i64; 12 typedef pair<int, int> pii; 13 const int inf = ~0U >> 1; 14 const i64 INF = ~0ULL >> 1; 15 //******************************** 16 const int maxn = 1005, maxm = 5005; 17 pair<int, pii> edge[maxm]; 18 int val[maxn], father[maxn], sze[maxn]; 19 inline int getfather(int x) { return father[x] == x ? x : father[x] = getfather(father[x]); } 20 int main() { 21 int n, m, k; 22 scanf("%d%d%d", &n, &m, &k); 23 rep(i, 1, n) scanf("%d", &val[i]); 24 rep(i, 1, m) scanf("%d%d%d", &edge[i].yy.xx, &edge[i].yy.yy, &edge[i].xx); 25 sort(edge + 1, edge + 1 + m); 26 int ret = inf; 27 rep(i, 1, m) { 28 rep(o, 1, n) sze[o] = 1, father[o] = o; 29 int ans = n * val[1]; 30 rep(j, i, m) { 31 if (j != i && edge[j].xx != edge[j - 1].xx) { 32 if (ans >= k) { 33 ret = min(ret, edge[j - 1].xx - edge[i].xx); 34 break; 35 } 36 } 37 int fx = getfather(edge[j].yy.xx), fy = getfather(edge[j].yy.yy); 38 if (fx != fy) { 39 father[fy] = fx; 40 ans -= val[sze[fy]] + val[sze[fx]]; 41 sze[fx] += sze[fy]; 42 sze[fy] = 0; 43 ans += val[sze[fx]]; 44 } 45 } 46 if (ans >= k) ret = min(ret, edge[m].xx - edge[i].xx); 47 } 48 if (ret == inf) puts("T_T"); 49 else printf("%d\n", ret); 50 return 0; 51 }