UVALive6900 Road Repair(树的点分治)

题目大概说一棵树,树边有费用和收益两个属性,求一条收益和最大的路径满足费用和不超过C。

树上任意两点的路径都可以看成是过某一个子树根的路径,显然树分治。

治的时候要解决的一个问题是,找到费用小于等于某个数且收益最大的值。

这个很容易想到用线段树,不过不想写线段树。。

想了想,想到可以先排序,从小到大去找,之前找到哪现在就继续从那儿开始找,这样最多也就遍历一遍待查找数组,具体看代码。

两次排序占大头,最后时间复杂度是O(nlog2n)。

WA了一次,因为只考虑了两端都过根的路径,忽略了一端点是根的路径。。之前写树分治也是因为这个WA。。

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<algorithm>
  4 using namespace std;
  5 #define INF (1<<30)
  6 #define MAXN 22222
  7 struct Edge{
  8     int v,b,c,next;
  9 }edge[MAXN<<1];
 10 int NE,head[MAXN];
 11 void addEdge(int u,int v,int b,int c){
 12     edge[NE].v=v; edge[NE].b=b; edge[NE].c=c; edge[NE].next=head[u];
 13     head[u]=NE++;
 14 }
 15 bool vis[MAXN];
 16 int size[MAXN];
 17 void getsize(int u,int fa){
 18     size[u]=1;
 19     for(int i=head[u]; i!=-1; i=edge[i].next){
 20         int v=edge[i].v;
 21         if(v==fa || vis[v]) continue;
 22         getsize(v,u);
 23         size[u]+=size[v];
 24     }
 25 }
 26 int mm,cen;
 27 void getcen(int u,int fa,int &tot){
 28     int res=tot-size[u];
 29     for(int i=head[u]; i!=-1; i=edge[i].next){
 30         int v=edge[i].v;
 31         if(v==fa || vis[v]) continue;
 32         getcen(v,u,tot);
 33         res=max(res,size[v]);
 34     }
 35     if(res<mm){
 36         mm=res;
 37         cen=u;
 38     }
 39 }
 40 int getcen(int u){
 41     getsize(u,u);
 42     mm=INF;
 43     getcen(u,u,size[u]);
 44     return cen;
 45 }
 46 struct Rec{
 47     int b,c;
 48     bool operator<(const Rec &r)const{
 49         return c<r.c;
 50     }
 51 }ra[MAXN],rb[MAXN];
 52 int tot,an,bn;
 53 void dfs(int u,int fa,int benfit,int cost){
 54     rb[bn].b=benfit;
 55     rb[bn].c=cost;
 56     bn++;
 57     for(int i=head[u]; i!=-1; i=edge[i].next){
 58         int v=edge[i].v;
 59         if(v==fa || vis[v]) continue;
 60         dfs(v,u,benfit+edge[i].b,cost+edge[i].c);
 61     }
 62 }
 63 int ans;
 64 void conqur(int u){
 65     an=1;
 66     ra[0].b=0; ra[0].c=0;
 67     for(int i=head[u]; i!=-1; i=edge[i].next){
 68         int v=edge[i].v;
 69         if(vis[v]) continue;
 70         bn=0;
 71         dfs(v,v,edge[i].b,edge[i].c);
 72         sort(ra,ra+an);
 73         sort(rb,rb+bn);
 74         int pa=an-1,pb=0;
 75         while(pb<bn){
 76             int mx=-1;
 77             for(int j=pa; j>=0; --j){
 78                 if(ra[j].c+rb[pb].c<=tot){
 79                     if(mx<ra[j].b+rb[pb].b){
 80                         mx=ra[j].b+rb[pb].b;
 81                         pa=j;
 82                     }
 83                 }
 84             }
 85             if(mx==-1) break;
 86             ans=max(ans,mx);
 87             ++pb;
 88         }
 89         for(int j=0; j<bn; ++j){
 90             ra[an++]=rb[j];
 91         }
 92     }
 93 }
 94 void divide(int u){
 95     u=getcen(u);
 96     vis[u]=1;
 97     conqur(u);
 98     for(int i=head[u]; i!=-1; i=edge[i].next){
 99         int v=edge[i].v;
100         if(vis[v]) continue;
101         divide(v);
102     }
103 }
104 int main(){
105     int t,n,a,b,c,d;
106     scanf("%d",&t);
107     while(t--){
108         scanf("%d",&n);
109         NE=0;
110         memset(head,-1,sizeof(head));
111         for(int i=1; i<n; ++i){
112             scanf("%d%d%d%d",&a,&b,&c,&d);
113             addEdge(a,b,d,c);
114             addEdge(b,a,d,c);
115         }
116         scanf("%d",&tot);
117         ans=0;
118         memset(vis,0,sizeof(vis));
119         divide(1);
120         printf("%d\n",ans);
121     }
122     return 0;
123 }
时间: 2024-10-12 19:42:33

UVALive6900 Road Repair(树的点分治)的相关文章

hdu_5314_Happy King(树的点分治)

题目链接:hdu_5314_Happy King 题意: 给出一颗n个结点的树,点上有权值: 求点对(x,y)满足x!=y且x到y的路径上最大值与最小值的差<=D: 题解: 还是树的点分治,在统计答案的时候先按到根的最小值排序,然后用最大值减D去找有多少个满足答案. 1 #include<bits/stdc++.h> 2 #define F(i,a,b) for(int i=a;i<=b;++i) 3 using namespace std; 4 typedef pair<i

bzoj 3435: [Wc2014]紫荆花之恋 替罪羊树维护点分治 &amp;&amp; AC400

3435: [Wc2014]紫荆花之恋 Time Limit: 240 Sec  Memory Limit: 512 MBSubmit: 159  Solved: 40[Submit][Status][Discuss] Description 强 强和萌萌是一对好朋友.有一天他们在外面闲逛,突然看到前方有一棵紫荆树.这已经是紫荆花飞舞的季节了,无数的花瓣以肉眼可见的速度从紫荆树上长了出来. 仔细看看的话,这个大树实际上是一个带权树.每个时刻它会长出一个新的叶子节点.每个节点上有一个可爱的小精灵,

bzoj 2152: 聪聪可可 树的点分治

2152: 聪聪可可 Time Limit: 3 Sec  Memory Limit: 259 MBSubmit: 485  Solved: 251[Submit][Status] Description 聪聪和可可是兄弟俩,他们俩经常为了一些琐事打起来,例如家中只剩下最后一根冰棍而两人都想吃.两个人都想玩儿电脑(可是他们家只有一台电脑)……遇到这种问题,一般情况下石头剪刀布就好了,可是他们已经玩儿腻了这种低智商的游戏.他们的爸爸快被他们的争吵烦死了,所以他发明了一个新游戏:由爸爸在纸上画n个“

【bzoj3672】[Noi2014]购票 斜率优化+CDQ分治+树的点分治

题目描述 给出一棵以1为根的带边权有根树,对于每个根节点以外的点$v$,如果它与其某个祖先$a$的距离$d$不超过$l_v$,则可以花费$p_vd+q_v$的代价从$v$到$a$.问从每个点到1花费的最小代价(中途可以经停其它点) 输入 第 1 行包含2个非负整数 n,t,分别表示城市的个数和数据类型(其意义将在后面提到).输入文件的第 2 到 n 行,每行描述一个除SZ之外的城市.其中第 v 行包含 5 个非负整数 $f_v,s_v,p_v,q_v,l_v$,分别表示城市 v 的父亲城市,它到

【bzoj1316】树上的询问 树的点分治+STL-set

题目描述 一棵n个点的带权有根树,有p个询问,每次询问树中是否存在一条长度为Len的路径,如果是,输出Yes否输出No. 输入 第一行两个整数n, p分别表示点的个数和询问的个数. 接下来n-1行每行三个数x, y, c,表示有一条树边x→y,长度为c. 接下来p行每行一个数Len,表示询问树中是否存在一条长度为Len的路径. 输出 输出有p行,Yes或No. 样例输入 6 4 1 2 5 1 3 7 1 4 1 3 5 2 3 6 3 1 8 13 14 样例输出 Yes Yes No Yes

【bzoj4016】[FJOI2014]最短路径树问题 堆优化Dijkstra+DFS树+树的点分治

题目描述 给一个包含n个点,m条边的无向连通图.从顶点1出发,往其余所有点分别走一次并返回. 往某一个点走时,选择总长度最短的路径走.若有多条长度最短的路径,则选择经过的顶点序列字典序最小的那条路径(如路径A为1,32,11,路径B为1,3,2,11,路径B字典序较小.注意是序列的字典序的最小,而非路径中节点编号相连的字符串字典序最小).到达该点后按原路返回,然后往其他点走,直到所有点都走过. 可以知道,经过的边会构成一棵最短路径树.请问,在这棵最短路径树上,最长的包含K个点的简单路径长度为多长

hdu 4081 Qin Shi Huang&#39;s National Road System 树的基本性质 or 次小生成树

During the Warring States Period of ancient China(476 BC to 221 BC), there were seven kingdoms in China ---- they were Qi, Chu, Yan, Han, Zhao, Wei and Qin. Ying Zheng was the king of the kingdom Qin. Through 9 years of wars, he finally conquered all

HDU4812 D Tree(树的点分治)

题目大概说给一棵有点权的树,输出字典序最小的点对,使这两点间路径上点权的乘积模1000003的结果为k. 树的点分治搞了.因为是点权过根的两条路径的LCA会被重复统计,而注意到1000003是质数,所以这个用乘法逆元搞一下就OK了.还有要注意“治”的各个实现,把时间复杂度“控制”在O(nlogn). WA了几次,WA在漏了点到子树根的路径,还有每次分治忘了清空数组. 1 #include<cstdio> 2 #include<cstring> 3 #include<algor

【bzoj3362/3363/3364/3365】[Usaco2004 Feb]树上问题杂烩 并查集/树形dp/LCA/树的点分治

题目描述 农夫约翰有N(2≤N≤40000)个农场,标号1到N,M(2≤M≤40000)条的不同的垂直或水平的道路连结着农场,道路的长度不超过1000.这些农场的分布就像下面的地图一样, 图中农场用F1..F7表示, 每个农场最多能在东西南北四个方向连结4个不同的农场.此外,农场只处在道路的两端.道路不会交叉且每对农场间有且仅有一条路径.邻居鲍伯要约翰来导航,但约翰丢了农场的地图,他只得从电脑的备份中修复了.每一条道路的信息如下: 从农场23往南经距离10到达农场17 从农场1往东经距离7到达农