51nod1307(暴力树剖/二分&dfs/并查集)
题目链接: http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1307
题意: 中文题诶~
思路:
解法1:暴力树剖
用一个数组 num[i] 维护编号为 i 的边当前最大能承受的重量. 在加边的过程中根据给出的父亲节点将当前边所在的链上所有边的num都减去当前加的边的重量, 注意当前边也要减自重. 那么当num首次出现负数时加的边号即位答案;
事实上这个算法的时间复杂度是O(n^2)的, 不过本题并没有出那种退化成单链的数据, 所以直接暴力也能水过;
代码:
#include <iostream>
#include <stdio.h>
using namespace std; const int MAXN = 5e4 + ;
struct node{
int c, w, pre;
}gel[MAXN];
int num[MAXN];//num[i]为编号为i的绳子当前可以承受的最大重量 int main(void){
int n, ans = -;
scanf("%d", &n);
for(int i = ; i < n; i++){
scanf("%d%d%d", &gel[i].c, &gel[i].w, &gel[i].pre);
if(ans != -) continue;
num[i] = gel[i].c;
int cnt = i;
while(cnt != -){
num[cnt] -= gel[i].w;
if(ans == - && num[cnt] <= -) ans = i;
cnt = gel[cnt].pre;//指向cnt的父亲节点
}
}
if(ans == -) cout << n << endl;
else cout << ans << endl;
return ;
}
解法2: 二分 + dfs
很显然在加边的过程中所有边的承受重量都是单调不减的, 那么可以考虑二分答案. 不过要注意判断函数的写法, 每一次判断都需要判断当前 mid条 边组成的树的所有边, 而不能只判断当前 mid 所在链上的边, 显然其他链上也可能存在不合法的边. 判断所有边的话可以 dfs 一遍, 回溯时判断即可.
代码:
#include <iostream>
#include <stdio.h>
#include <vector>
#define ll long long
using namespace std; const int MAXN = 5e4 + ;
struct node{
int c, w, pre;
}gel[MAXN];
vector<int> sol[MAXN];
bool flag; ll dfs(int u, int x){
ll sum = gel[u].w;
if(u > x) return ;//mid边后面的不要算上去
for(int i = ; i < sol[u].size(); i++){
sum += dfs(sol[u][i], x);
}
if(sum > gel[u].c && u) flag = false;//0是一个虚根,并没有对应的边
return sum;
} int main(void){
int n;
scanf("%d", &n);
for(int i = ; i <= n; i++){
scanf("%d%d%d", &gel[i].c, &gel[i].w, &gel[i].pre);
gel[i].pre++;
sol[gel[i].pre].push_back(i);
}
int l = , r = n, cnt = n;
while(l <= r){
flag = true;
int mid = (l + r) >> ;
dfs(, mid);
if(flag) cnt = mid, l = mid + ;
else r = mid - ;
}
printf("%d\n", cnt);
}
解法3: 并查集
#include <iostream>
#include <stdio.h>
#include <vector>
#define ll long long
using namespace std; const int MAXN = 1e5 + ;
struct node{
ll c, w, p;
}gel[MAXN]; ll ww[MAXN];
vector<int> vt[MAXN];
int pre[MAXN], sol; int find(int x){
return pre[x] == x ? x : pre[x] = find(pre[x]);
} void update(int u){
for(int i = ; i < vt[u].size(); i++){
gel[u].w += gel[vt[u][i]].w;
pre[vt[u][i]] = u;
}
while(gel[u].w > gel[u].c){//u即为当前根节点
gel[find(sol)].w -= ww[sol];
sol--;
}
} int main(void){
int n;
scanf("%d", &n);
for(int i = ; i <= n; i++){
scanf("%lld%lld%lld", &gel[i].c, &gel[i].w, &gel[i].p);
gel[i].p++;
vt[gel[i].p].push_back(i);
ww[i] = gel[i].w;//后面会对gel操作,所以需要先记录下gel的初始值来
pre[i] = i;
}
sol = n;
for(int i = n; i > ; i--){
update(i);
}
printf("%d\n", sol);
return ;
}
51nod1307(暴力树剖/二分&dfs/并查集)的更多相关文章
- 【CF576E】Painting Edges 线段树按时间分治+并查集
[CF576E]Painting Edges 题意:给你一张n个点,m条边的无向图,每条边是k种颜色中的一种,满足所有颜色相同的边内部形成一个二分图.有q个询问,每次询问给出a,b代表将编号为a的边染 ...
- BZOJ_4025_二分图_线段树按时间分治+并查集
BZOJ_4025_二分图_线段树按时间分治+并查集 Description 神犇有一个n个节点的图.因为神犇是神犇,所以在T时间内一些边会出现后消失.神犇要求出每一时间段内这个图是否是二分图.这么简 ...
- 【BZOJ1821】[JSOI2010]部落划分(二分,并查集)
[BZOJ1821][JSOI2010]部落划分(二分,并查集) 题面 BZOJ 洛谷 题解 二分答案,把距离小于二分值的点全部并起来,\(\mbox{check}\)一下是否有超过\(K\)个集合就 ...
- 洛谷P4145 上帝造题的七分钟2/花神游历各国 [树状数组,并查集]
题目传送门 题目背景 XLk觉得<上帝造题的七分钟>不太过瘾,于是有了第二部. 题目描述 "第一分钟,X说,要有数列,于是便给定了一个正整数数列. 第二分钟,L说,要能修改,于是 ...
- 【bzoj3007】拯救小云公主 二分+对偶图+并查集
题目描述 英雄又即将踏上拯救公主的道路…… 这次的拯救目标是——爱和正义的小云公主. 英雄来到boss的洞穴门口,他一下子就懵了,因为面前不只是一只boss,而是上千只boss.当英雄意识到自己还是等 ...
- [HNOI2006]公路修建问题 (二分答案,并查集)
题目链接 Solution 二分答案+并查集. 由于考虑到是要求花费的最小值,直接考虑到二分. 然后对于每一个二分出来的答案,模拟 \(Kruskal\) 的过程再做一遍连边. 同时用并查集维护联通块 ...
- BZOJ 4034 [HAOI2015]树上操作 线段树+树剖或dfs
题意 直接照搬原题面 有一棵点数为 N 的树,以点 1 为根,且树点有边权.然后有 M 个 操作,分为三种: 操作 1 :把某个节点 x 的点权增加 a . 操作 2 :把某个节点 x 为根的子树中所 ...
- CF 115 A 【求树最大深度/DFS/并查集】
CF A. Party time limit per test3 seconds memory limit per test256 megabytes inputstandard input outp ...
- hdu 5652 India and China Origins(二分+bfs || 并查集)BestCoder Round #77 (div.2)
题意: 给一个n*m的矩阵作为地图,0为通路,1为阻碍.只能向上下左右四个方向走.每一年会在一个通路上长出一个阻碍,求第几年最上面一行与最下面一行会被隔开. 输入: 首行一个整数t,表示共有t组数据. ...
随机推荐
- OpenCV——径向模糊
参考来源: 学习OpenCV:滤镜系列(5)--径向模糊:缩放&旋转 // define head function #ifndef PS_ALGORITHM_H_INCLUDED #defi ...
- Python语言及其应用 第2章
- BZOJ3812 清华集训2014 主旋律
直接求出强联通生成子图的数量较难,不妨用所有生成子图的数量减去非强联通的. 非强联通生成子图在所点后满足编号最小的点所在的强联通分量不是全集. 由于$n$很小,我们可以考虑状态压缩. 对于点集$S$, ...
- Gym 101142C :CodeCoder vs TopForces(强连通算法)
题意:N个人,每个人有a属性和b属性,如果一个人的a或者b大于另外一个人,我们说这个人可以打败那个人.且这种关系可以传递.对于每个人,输出他可以打败多少人.(保证每个a不相同,保证每个b不相同. 思路 ...
- URL、SRC、HREF知识整理
今天理一下URL.SRC.HREF定义以及使用区别. URL(Uniform Resource Locator) 统一资源定位符是对可以从互联网上得到的资源的位置和访问方法的一种简洁的表示,是互联网上 ...
- gradle项目搭建
一.gradle安装 1.安装JDK,这个就不用说了 2.下载gradle发布文件,下载地址:http://gradle.org/gradle-download/可以下载完整版或者简洁版都可以 3.解 ...
- 照片Urls
http://img.my.csdn.net/uploads/201402/16/1392530364_7835.jpg http://img.my.csdn.net/uploads/201402/1 ...
- jquery 键盘事件的使用方法详解
转自:https://www.jb51.net/article/123579.htm jQuery处理键盘事件有三个函数,根据事件发生的顺序分别是: jquery 代码: 1. keydown(); ...
- Tiny4412学习杂记
1.Android 挂载NFS 使用 busybox mount 来替代mount命令 2.修改Uboot中fastboot最大buff 使用U-boot烧写Android5.0的时候出现 remo ...
- struts 文件上传示例
import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io ...