您的位置:首页 > 其它

51nod1307(暴力树剖/二分&dfs/并查集)

2017-07-05 15:41 375 查看
题目链接: http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1307

题意: 中文题诶~

思路:

解法1:暴力树剖

用一个数组 num[i] 维护编号为 i 的边当前最大能承受的重量. 在加边的过程中根据给出的父亲节点将当前边所在的链上所有边的num都减去当前加的边的重量, 注意当前边也要减自重. 那么当num首次出现负数时加的边号即位答案;

事实上这个算法的时间复杂度是O(n^2)的, 不过本题并没有出那种退化成单链的数据, 所以直接暴力也能水过;

代码:

1 #include <iostream>
2 #include <stdio.h>
3 #include <vector>
4 #define ll long long
5 using namespace std;
6
7 const int MAXN = 1e5 + 10;
8 struct node{
9     ll c, w, p;
10 }gel[MAXN];
11
12 ll ww[MAXN];
13 vector<int> vt[MAXN];
14 int pre[MAXN], sol;
15
16 int find(int x){
17     return pre[x] == x ? x : pre[x] = find(pre[x]);
18 }
19
20 void update(int u){
21     for(int i = 0; i < vt[u].size(); i++){
22         gel[u].w += gel[vt[u][i]].w;
23         pre[vt[u][i]] = u;
24     }
25     while(gel[u].w > gel[u].c){//u即为当前根节点
26         gel[find(sol)].w -= ww[sol];
27         sol--;
28     }
29 }
30
31 int main(void){
32     int n;
33     scanf("%d", &n);
34     for(int i = 1; i <= n; i++){
35         scanf("%lld%lld%lld", &gel[i].c, &gel[i].w, &gel[i].p);
36         gel[i].p++;
37         vt[gel[i].p].push_back(i);
38         ww[i] = gel[i].w;//后面会对gel操作,所以需要先记录下gel的初始值来
39         pre[i] = i;
40     }
41     sol = n;
42     for(int i = n; i > 0; i--){
43         update(i);
44     }
45     printf("%d\n", sol);
46     return 0;
47 }


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: