题目链接:

http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1307

题意:

题解:

方法一:
因为所有绳子最终组成了1棵树,所以我们可以通过一次DFS,来检测是否有某根绳子下面绑了超过他所能负荷的重量。
具体方法:对每个节点,计算其子树的重量和(包含自身的重量),如果大于能承受的最大重量,则绳子会断,否则不会断。
一次DFS时间复杂度是O(n)的。
既然一次判断的复杂度是O(n)的,并且当绳子第一次断掉后,继续放重物,不会改变绳子断掉的状态(毕竟重物的重量都是正数,没有负数),那么我们可以用二分来做。
二分来求第一次断掉的点,由于二分的复杂度是log(n),一次DFS判断的复杂度是O(n),所以整个算法的复杂度是nlog(n)。
二分经常被用来求解一些具有单调性的问题,这里的单调性就是断掉以后,不会再次变成不断的。

方法二:
我们在DFS的过程中,使用并查集,将子树节点的Root指向当前节点,同时计算子树的总重量。
假如当前节点的承重不足,那么绳子会断掉。所以我们需要去掉一些节点,来保证绳子不断。根据题目要求,我们按照子树节点的编号从高到低,逐个去掉这些重物,直到绳子不断为止。
那么问题来了,并查集这个结构并不能解决按照编号从高到低去掉子树的问题,如果自己维护其他的数据结构(比如堆),恐怕复杂度还要多一个Log。

所以我们跳出按照编号从高到低去掉子树的思路,不如直接从编号N - 1到0去掉子树,直到当前的绳子不断为止。 因为编号小的断了,后面再加的绳子也没有用了,已经有绳子断了就结束了。

代码:

二分:

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 #define MS(a) memset(a,0,sizeof(a))
 5 #define MP make_pair
 6 #define PB push_back
 7 const int INF = 0x3f3f3f3f;
 8 const ll INFLL = 0x3f3f3f3f3f3f3f3fLL;
 9 inline ll read(){
10     ll x=0,f=1;char ch=getchar();
11     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
12     while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
13     return x*f;
14 }
15 //
16 const int maxn = 1e5+10;
17
18 struct node{
19     int c,w,f;
20 }e[maxn];
21
22 vector<int> g[maxn];
23
24 bool book;
25
26 ll dfs(int u,int k){
27     ll sum = e[u].w;
28     if(u > k) return 0;
29     for(auto v : g[u])
30         sum += dfs(v,k);
31     if(sum > e[u].c && u) book = false;
32     return sum;
33 }
34
35 int main(){
36     int n=read();
37     for(int i=1; i<=n; i++){
38         e[i].c=read(); e[i].w=read(); e[i].f=read(); e[i].f++;
39         g[e[i].f].push_back(i);
40     }
41
42     int l=0,r=n,ans = 0;
43     while(l<=r){
44         int mid = (l+r)/2;
45         book = true;
46         dfs(0,mid);
47         if(book) ans=mid,l=mid+1;
48         else r=mid-1;
49     }
50
51     cout << ans << endl;
52
53     return 0;
54 }

并查集:

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 #define MS(a) memset(a,0,sizeof(a))
 5 #define MP make_pair
 6 #define PB push_back
 7 const int INF = 0x3f3f3f3f;
 8 const ll INFLL = 0x3f3f3f3f3f3f3f3fLL;
 9 inline ll read(){
10     ll x=0,f=1;char ch=getchar();
11     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
12     while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
13     return x*f;
14 }
15 //
16 const int maxn = 1e5+10;
17
18 struct node{
19     ll c,w,f;
20 }e[maxn];
21
22 vector<int> g[maxn];
23 int fa[maxn];
24 ll ww[maxn];
25 int k;
26
27 int find(int x){
28     return fa[x]==x ? x : fa[x]=find(fa[x]);
29 }
30
31 void update(int u){
32     for(auto v : g[u]){
33         e[u].w += e[v].w;
34         fa[v] = u;
35     }
36
37     while(e[u].w > e[u].c){
38         e[find(k)].w -= ww[k];
39         k--;
40     }
41 }
42
43 int main(){
44     int n=read();
45     for(int i=1; i<=n; i++){
46         e[i].c=read(); e[i].w=read(); e[i].f=read(); e[i].f++;
47         g[e[i].f].push_back(i); ww[i] = e[i].w;
48         fa[i] = i;
49     }
50
51     k = n;
52     for(int i=n; i>0; i--)
53         update(i);
54
55     cout << k << endl;
56
57     return 0;
58 }

转载于:https://www.cnblogs.com/yxg123123/p/6827576.html

51nod 1307 绳子与重物 二分+dfs / 并查集相关推荐

  1. 51nod 1307 绳子与重物 (标记父节点更新即可)

    1307 绳子与重物 基准时间限制:1 秒 空间限制:131072 KB 分值: 40 难度:4级算法题 有N条绳子编号 0 至 N - 1,每条绳子后面栓了一个重物重量为Wi,绳子的最大负重为Ci. ...

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

    题目链接: http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1307 题意: 中文题诶~ 思路: 解法1:暴力树剖 用一个数 ...

  3. Codeforces Round #260 (Div. 1) C. Civilization(dfs+并查集)

    time limit per test1 second memory limit per test256 megabytes inputstandard input outputstandard ou ...

  4. 分珠(dfs+并查集)

    1140 分珠 时间限制:500MS  内存限制:65536K 提交次数:24 通过次数:18 题型: 编程题   语言: G++;GCC Description 如下图所示,有若干珠子,每颗珠子重量 ...

  5. 【蓝桥杯官网试题 - 历届试题】发现环(dfs+并查集,或无向图tarjan判环,无向环,或拓扑排序)

    题干: 问题描述 小明的实验室有N台电脑,编号1~N.原本这N台电脑之间有N-1条数据链接相连,恰好构成一个树形网络.在树形网络上,任意两台电脑之间有唯一的路径相连. 不过在最近一次维护网络时,管理员 ...

  6. LeetCode 1319. 连通网络的操作次数(BFS/DFS/并查集)

    文章目录 1. 题目 2. 解题 2.1 BFS 2.2 DFS 2.3 并查集 1. 题目 用以太网线缆将 n 台计算机连接成一个网络,计算机的编号从 0 到 n-1. 线缆用 connection ...

  7. Codeforces Round #548 (Div. 2) C. Edgy Trees(dfs || 并查集)

    题目链接:https://codeforces.com/contest/1139/problem/C 题意:给了一棵树,n个点,m条边.让从中选k个点,使得从a1到a2,a2到a3,ak-1到ak的路 ...

  8. L2-026 小字辈——BFS DFS 并查集-三种方法

    输入格式: 输入在第一行给出家族人口总数 N(不超过 100 000 的正整数) -- 简单起见,我们把家族成员从 1 到 N 编号.随后第二行给出 N 个编号,其中第 i 个编号对应第 i 位成员的 ...

  9. LeetCode 886. 可能的二分法(着色DFS/BFS/拓展并查集)

    文章目录 1. 题目 2. 解题 2.1 DFS 2.2 BFS 2.3 并查集 1. 题目 给定一组 N 人(编号为 1, 2, -, N), 我们想把每个人分进任意大小的两组. 每个人都可能不喜欢 ...

最新文章

  1. 【高级Java架构师系统学习】java十六进制字符串转数字
  2. Javascript小括号“()”的多义性
  3. 改正错误:tensorflow.python.framework.errors_impl.NotFoundError: FindFirstFile failed for: ...
  4. 参考文献顺序不对_Endnote插入参考文献的保姆级教程
  5. CTF Geek Challenge——第十一届极客大挑战Misc Write Up
  6. python数学计算函数_Python 内置函数(数学运算类,逻辑判断类)
  7. Linux下安装nginx (tar解压版安装) nginx1.16.1
  8. Linux 命令之 kill -- 杀死进程
  9. pythonwhile循环love_input和while循环——Python编程从入门到实践
  10. python中的递归函数是什么_Python中的递归函数
  11. 【算法学习笔记】03.白书练习题stat(排序入门:冒泡,桶)
  12. ceph rbd 封装api
  13. web前端-HTML 媒体插件 022
  14. 贝叶斯网络python实现_在Python中使用贝叶斯网络的实例
  15. (附源码)ssm天天超市购物网站 毕业设计 022101
  16. KM算法实现带权匹配C#版本和C++两个版本实现O^3
  17. 手机玩exe游戏的模拟器_手机就能玩Switch游戏,蛋蛋模拟器+盖世小鸡X2手柄体验...
  18. 什么是ArcGIS Engine?
  19. Loadbalancer
  20. 鸢尾花分类算法——机器学习笔记

热门文章

  1. mysql5.7安装差异_mysql5.7和mysql5.6同在CentOS7.4安装差异对比之5.7.18
  2. 数据结构之栈对逆BoLand表达式的计算
  3. appium学习记录1
  4. gitlab用户添加ssh免密钥认证后clone还是要求输入密码
  5. 软件与软件工程的概念
  6. JAVA可阻塞队列-ArrayBlockingQueue
  7. HDU1232——通畅工程(并查集)
  8. 三阶矩阵的lu分解详细步骤_快速入门矩阵运算——开源库Eigen
  9. Promise解决多个异步Ajax请求导致的代码嵌套问题(完美解决方案)
  10. 原型 原型链 call / apply