UVa 12161 Ironman Race in Treeland(树分治)
来源:互联网 发布:淘宝店铺处罚规则 编辑:程序博客网 时间:2024/05/20 04:49
题目大意:
有一棵树,每条边上都有花费和长度,求花费不超过M的最长路径。
解题思路:
比较典型的树分治,对于每个重心,统计所有经过重心的路径的组合,再加上原始输入的边,一定能够得到所有的路径。在计算组合的时候,直接暴力枚举非常低效,我们可以先去掉花费大,长度短的路径,然后排序利用双指针(具体写法见代码)。
AC代码:
#include <iostream>#include <algorithm>#include <cstdio>#include <cstring>#include <cstdlib>#include <cmath>#include <ctime>#include <vector>#include <queue>#include <stack>#include <deque>#include <string>#include <map>#include <set>#include <list>using namespace std;#define INF 0x3f3f3f3f#define LL long long#define fi first#define se second#define mem(a,b) memset((a),(b),sizeof(a))const int MAXV=30000+3;struct Edge{ int to, damage, length, next; Edge(int t=0, int d=0, int l=0, int n=0):to(t), damage(d), length(l), next(n){}}edge[MAXV*2];int N, M;int head[MAXV], edge_size;int ans, pre_max_subtree_size;//重心最大子树大小int pre_subtree_size;//以u为根的子树大小int subtree_size[MAXV];//以i为根的子树的节点数bool is_centroid[MAXV];//是否为重心pair<int, int> path[MAXV];int b, e;//当前子树中路径在path[]中的开始下标和结束下标void init(){ ans=0; edge_size=0; mem(head, -1);}void add_edge(int from, int to, int damage, int length){ edge[edge_size]=Edge(to, damage, length, head[from]); head[from]=edge_size++;}//查找重心的递归函数//在以u为根的子树中寻找一个顶点,使得删除该该节点后最大子树的顶点数最小void search_centroid(int u, int fa, int &root){ int max_subtree_size=0; subtree_size[u]=1; for(int i=head[u];~i;i=edge[i].next) { int v=edge[i].to; if(v==fa || is_centroid[v]) continue; search_centroid(v, u, root); max_subtree_size=max(max_subtree_size, subtree_size[v]); subtree_size[u]+=subtree_size[v]; } max_subtree_size=max(max_subtree_size, pre_subtree_size-subtree_size[u]);//计算u所在的子树的结点数 if(max_subtree_size<pre_max_subtree_size)//更换重心 { root=u; pre_max_subtree_size=max_subtree_size; }}//计算子树大小(subtree_size)的递归函数int compute_subtree_size(int u, int fa){ int res=1; for(int i=head[u];~i;i=edge[i].next) { int v=edge[i].to; if(v==fa || is_centroid[v]) continue; res+=compute_subtree_size(v, u); } return res;}//计算子树中的所有顶点到重心的距离void enumerate_paths(int u, int fa, int damage, int length){ path[e++]=make_pair(damage, length); for(int i=head[u];~i;i=edge[i].next) { int v=edge[i].to; if(v==fa || is_centroid[v]) continue; if(damage+edge[i].damage<=M) enumerate_paths(v, u, damage+edge[i].damage, length+edge[i].length); }}//删除长度小,花费大的路径void remove_useless(int b, int &e){ if(b==e) return ; int size; for(int i=size=b+1;i<e;++i) { if(path[i].fi==path[size-1].fi) continue; if(path[i].se<=path[size-1].se) continue; path[size++]=path[i]; } e=size;}void solve_sub_problem(int u, int fa){ for(int i=head[u];~i;i=edge[i].next) { int v=edge[i].to; if(v==fa || is_centroid[v]) continue; pre_max_subtree_size=MAXV; pre_subtree_size=compute_subtree_size(v, u); int root; search_centroid(v, u, root); is_centroid[root]=1; solve_sub_problem(root, u); is_centroid[root]=0; } b=e=0; for(int i=head[u];~i;i=edge[i].next) { int v=edge[i].to; if(v==fa || is_centroid[v]) continue; if(edge[i].damage<=M) enumerate_paths(v, u, edge[i].damage, edge[i].length); if(b>0)//合并不同子树之间经过重心的路径 { sort(path+b, path+e); remove_useless(b, e); for(int _b=0, _e=e-1;_b<b;++_b) { while(_e>=b && path[_b].fi+path[_e].fi>M) --_e; if(_e>=b) ans=max(ans, path[_b].se+path[_e].se); } } sort(path, path+e); remove_useless(0, e); b=e; }}int main(){ int T_T; scanf("%d", &T_T); for(int cas=1;cas<=T_T;++cas) { scanf("%d%d", &N, &M); init(); for(int i=1;i<N;++i) { int u, v, damage, length; scanf("%d%d%d%d", &u, &v, &damage, &length); --u; --v; add_edge(u, v, damage, length); add_edge(v, u, damage, length); if(damage<=M) ans=max(ans, length); } int root; pre_max_subtree_size=MAXV; pre_subtree_size=N; search_centroid(1, -1, root); is_centroid[root]=1; solve_sub_problem(root, -1); is_centroid[root]=0; printf("Case %d: %d\n", cas, ans); } return 0;}
阅读全文
0 0
- UVa 12161 Ironman Race in Treeland(树分治)
- [BZOJ2599][IOI2011]Race 树分治
- bzoj 2599: [IOI2011]Race(树的点分治)
- bzoj 2599 Race树的分治
- 2599: [IOI2011]Race|树的点分治
- Bzoj2599:[IOI2011]Race:树的点分治
- [BZOJ2599][IOI2011]Race(点分治)
- bzoj 2599: [IOI2011]Race (点分治)
- [BZOJ2599][IOI2011]Race(点分治)
- uva 12034 Race(dp)
- Race UVA
- bzoj2599 Race 点分治
- 【bzoj2599】Race 点分治
- UVA 12034:Race (动态规划)
- BZOJ 2599 IOI2011 Race 树的点分治
- BZOJ 2599 IOI 2011 Race 树的分治
- 【BZOJ 2599】 [IOI2011]Race 树的点分治
- [树的点分治] [树形DP] [BZOJ2599] [IOI2011] Race
- Python-Pandas(3)数据预处理
- 二分查找
- CSU 1203: Super-increasing sequence 水题
- 博弈——Good Luck in CET-4 Everybody!
- 详解spring 每个jar的作用
- UVa 12161 Ironman Race in Treeland(树分治)
- Leetcode--Two Sum
- lwip TCP client & FreeRTOS 打开TCP 的 保活机制 LWIP_TCP_KEEPALIVE==1
- CSU 1233: 病毒的复制 矩阵快速幂
- meanshift追踪手动选框(python-opencv)
- stl之双端队列deque
- hdu-6092-Rikka with Subset(思维)
- 散列查找
- CSU 1092: Barricade (dijkstra+heap)