题目链接: 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: 并查集

记录每个节点的父节点
然后按输入顺序的倒叙 遍历每一个节点
计算以当前节点为根的子树的重量 ( 因为按照题目的输入顺序来说  当前节点要么没有子节点  要么子树已经遍历完 算入当前树的重量)
当遍历到某个节点时
当前节点与父节点的边无法承载当前节点为根的子树  便从输入序列最晚输入的节点开始删除 
直到与父节点的边的能够承载当前节点为根的子树
又或者已经把遍历过的点都删除完了 
 
这个过程中  用并查集维护某个节点 属于那一个跟节点 并且不断的压缩路径
每个条路径被压缩一次 均摊时间 就是边的数量 所以 这种做法很稳定的 O(n)
 
上面这段话是直接从讨论中复制过来的
代码:
 #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/并查集)的更多相关文章

  1. 【CF576E】Painting Edges 线段树按时间分治+并查集

    [CF576E]Painting Edges 题意:给你一张n个点,m条边的无向图,每条边是k种颜色中的一种,满足所有颜色相同的边内部形成一个二分图.有q个询问,每次询问给出a,b代表将编号为a的边染 ...

  2. BZOJ_4025_二分图_线段树按时间分治+并查集

    BZOJ_4025_二分图_线段树按时间分治+并查集 Description 神犇有一个n个节点的图.因为神犇是神犇,所以在T时间内一些边会出现后消失.神犇要求出每一时间段内这个图是否是二分图.这么简 ...

  3. 【BZOJ1821】[JSOI2010]部落划分(二分,并查集)

    [BZOJ1821][JSOI2010]部落划分(二分,并查集) 题面 BZOJ 洛谷 题解 二分答案,把距离小于二分值的点全部并起来,\(\mbox{check}\)一下是否有超过\(K\)个集合就 ...

  4. 洛谷P4145 上帝造题的七分钟2/花神游历各国 [树状数组,并查集]

    题目传送门 题目背景 XLk觉得<上帝造题的七分钟>不太过瘾,于是有了第二部. 题目描述 "第一分钟,X说,要有数列,于是便给定了一个正整数数列. 第二分钟,L说,要能修改,于是 ...

  5. 【bzoj3007】拯救小云公主 二分+对偶图+并查集

    题目描述 英雄又即将踏上拯救公主的道路…… 这次的拯救目标是——爱和正义的小云公主. 英雄来到boss的洞穴门口,他一下子就懵了,因为面前不只是一只boss,而是上千只boss.当英雄意识到自己还是等 ...

  6. [HNOI2006]公路修建问题 (二分答案,并查集)

    题目链接 Solution 二分答案+并查集. 由于考虑到是要求花费的最小值,直接考虑到二分. 然后对于每一个二分出来的答案,模拟 \(Kruskal\) 的过程再做一遍连边. 同时用并查集维护联通块 ...

  7. BZOJ 4034 [HAOI2015]树上操作 线段树+树剖或dfs

    题意 直接照搬原题面 有一棵点数为 N 的树,以点 1 为根,且树点有边权.然后有 M 个 操作,分为三种: 操作 1 :把某个节点 x 的点权增加 a . 操作 2 :把某个节点 x 为根的子树中所 ...

  8. CF 115 A 【求树最大深度/DFS/并查集】

    CF A. Party time limit per test3 seconds memory limit per test256 megabytes inputstandard input outp ...

  9. hdu 5652 India and China Origins(二分+bfs || 并查集)BestCoder Round #77 (div.2)

    题意: 给一个n*m的矩阵作为地图,0为通路,1为阻碍.只能向上下左右四个方向走.每一年会在一个通路上长出一个阻碍,求第几年最上面一行与最下面一行会被隔开. 输入: 首行一个整数t,表示共有t组数据. ...

随机推荐

  1. 修改(python) mysql 数据库 使其可以支持插入中文

    先建立一个数据库,名字叫xsk #!/usr/bin/python3 # -*- coding:utf-8 -*- import pymsql # 打开数据库连接(本机,用户,密码,数据库名) db ...

  2. GeoServer基础教程(三):部署发布Shapefile地图数据

    转载:http://blog.csdn.net/mingzai624. 这是GeoServer官方网站提供的一份Shapefile测试数据 nyc_roads.zip ,包含了部分纽约的道路信息,我们 ...

  3. linux-常用指令3

    系统管理命令 stat              显示指定文件的详细信息,比ls更详细 who               显示在线登陆用户 whoami          显示当前操作用户 host ...

  4. pthread_cond_wait()用法分析

    很久没看APUE,今天一位朋友问道关于一个mutex的问题,又翻到了以前讨论过的东西,为了不让自己忘记,把曾经的东西总结一下. 先大体看下网上很多地方都有的关于pthread_cond_wait()的 ...

  5. 如何生成HLS协议的M3U8文件

    什么是HLS协议: HLS(Http Live Streaming)是由Apple公司定义的用于实时流传输的协议,HLS基于HTTP协议实现,传输内容包括两部分,一是M3U8描述文件,二是TS媒体文件 ...

  6. bzoj 3439: Kpm的MC密码 Trie+动态开点线段树

    题目大意: http://www.lydsy.com/JudgeOnline/problem.php?id=3439 题解: 首先我们发现这道题要查的是后缀不是前缀. 如果查前缀就可以迅速查找到字符串 ...

  7. 高级Java工程师必备 ----- 深入分析 Java IO (二)NIO

    接着上一篇文章 高级Java工程师必备 ----- 深入分析 Java IO (一)BIO,我们来讲讲NIO 多路复用IO模型 场景描述 一个餐厅同时有100位客人到店,当然到店后第一件要做的事情就是 ...

  8. NSArray用法

    //类方法初始化一个数组对象 [array count] : 得到这个数组对象的长度. [array objectAtIndex index]: 传入数组的索引(index) 得到数据对象. [arr ...

  9. RSA-CRT leaks__因使用中国余数定理计算RSA所引起的私钥泄露

    在heartbleed[1]漏洞后,很多用户打开了PFS[2]功能.但很不幸,之后RedHat又报告出在多个平台上存在RSA-CRT导致的密钥泄露[3]. 中国余数定理(CRT)常被用在RSA的计算中 ...

  10. altium designer 中的top/bottom solder和top/bottom paste mask

    转载请注明出处:http://blog.csdn.net/qq_26093511/article/details/51751936 1.top solder为助焊层,说白一点就是说,有这个层的地方就没 ...