• CS academy Growing Trees【模板】DP求树的直径


    【题意概述】

      给出一棵树,树上的边有两个值a和b,你可以在[0,limit]范围内选择一个整数delta,树上的边的权值为a+b*delta,现在问当delta为多少的时候树的直径最小、最小直径是多少。

    【题解】

      每条边的边权都是一次函数,那么直径是单峰函数。单峰函数求最小值我们可以用三分法。

      注意边权可能为负数,求直径时要用DP,而不能用dfs到最远点、再从最远点dfs到它的最远点的方法。

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 #define LL long long
     5 #define rg register
     6 #define N 500010
     7 using namespace std;
     8 int n,m,tot,del,l,r,last[N];
     9 LL ans=3e18,mx,dis[N][2];
    10 struct edge{
    11     int to,pre; LL w;
    12 }e[N<<1];
    13 struct rec{
    14     int u,v,a,b;
    15 }re[N];
    16 inline int read(){
    17     int k=0,f=1; char c=getchar();
    18     while(c<'0'||c>'9')c=='-'&&(f=-1),c=getchar();
    19     while('0'<=c&&c<='9')k=k*10+c-'0',c=getchar();
    20     return k*f;
    21 } 
    22 void dfs(int x,int fa){
    23     for(rg int i=last[x],to;i;i=e[i].pre)if((to=e[i].to)!=fa){
    24         dfs(to,x); LL tmp=dis[to][0]+e[i].w;
    25         if(tmp>=dis[x][0]){
    26             dis[x][1]=dis[x][0],dis[x][0]=tmp;
    27         }
    28         else
    29             if(tmp>dis[x][1]) dis[x][1]=tmp;
    30     }
    31     mx=max(mx,max(dis[x][0],dis[x][0]+dis[x][1]));
    32 }
    33 inline LL calc(int x){
    34     memset(last,0,sizeof(last)); tot=0;
    35     for(rg int i=1;i<n;i++){
    36         int u=re[i].u,v=re[i].v; LL w=re[i].a+re[i].b*x;
    37         e[++tot]=(edge){u,last[v],w}; last[v]=tot;
    38         e[++tot]=(edge){v,last[u],w}; last[u]=tot;
    39     }
    40     memset(dis,0,sizeof(dis)); mx=0;
    41     dfs(1,0);
    42     return mx;
    43 }
    44 signed main(){
    45     n=read(); l=-1; r=read();
    46     for(rg int i=1;i<n;i++){
    47         re[i].u=read(); re[i].v=read(); re[i].a=read(); re[i].b=read();
    48     }
    49     while(l+1<r){
    50         int mid1=(l+r)>>1,mid2=mid1+1;
    51         if(calc(mid1)<=calc(mid2)) r=mid1;
    52         else l=mid1;
    53     }
    54     printf("%d
    %lld
    ",r,calc(r));
    55     return 0;
    56 }
  • 相关阅读:
    菜鸟Vue学习笔记(二)
    菜鸟Vue学习笔记(一)
    JVM垃圾回收机制之对象回收算法
    什么是web前端开发?
    JDBC API阐述
    JDBC驱动程序分类
    JDBC理论知识
    冒泡排序(Bubble Sorting)
    Java 中几种常用设计模式
    数据库设计六大范式
  • 原文地址:https://www.cnblogs.com/DriverLao/p/9883009.html
Copyright © 2020-2023  润新知