• 【CF1016F】Road Projects(贪心)


    题意:给你一棵n 个节点的树,定义1n的代价是1到 n节点间的最短路径的长度。

    现在给你 m 组询问,让你添加一条边权为 w 的边(不与原图重复),求代价的最大值。询问之间相互独立。

    1n,m3×1e5,1<=c[i]<=1e9,1<=w<=1e9

    思路:网上dalao们的写法好像都和我不太一样……

    考虑将1-n路径上所有的点取出,则原树变成了一条链和若干条子树

    首先判断以链上某一点为根的子树size是否>=3,若是则可以在其内部连边,对最短路没有影响

    若没有则考虑在链上的点或者其延伸出的一个点(size<=2)中取某两个点上连边

    预处理出mx[u]代表u除链上儿子的子树最大深度

    则对于x,y(x在上y在下)两个点来说相对于原方案,新的方案增加了mx[x]+mx[y]-2*dis[y]的长度

    对于固定的y只需要维护mx[x]的前缀最大值

    需要注意的是不能连原树中有的边,即mx[x]=dis[x]和mx[y]=dis[y]不能同时成立,否则相当于同时取到链上相邻的两点

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<string>
      4 #include<cmath>
      5 #include<iostream>
      6 #include<algorithm>
      7 #include<map>
      8 #include<set>
      9 #include<queue>
     10 #include<vector>
     11 using namespace std;
     12 typedef long long ll;
     13 typedef unsigned int uint;
     14 typedef unsigned long long ull;
     15 typedef pair<int,int> PII;
     16 typedef vector<int> VI;
     17 #define fi first
     18 #define se second 
     19 #define MP make_pair
     20 #define N      310000
     21 #define M      51
     22 #define MOD 1000000007
     23 #define eps 1e-8 
     24 #define pi     acos(-1)
     25 #define oo     3e14
     26 
     27 struct node
     28 {
     29     int x,cost;
     30     node(int a,int b)
     31     {
     32          x=a;
     33          cost=b;
     34     }
     35 };
     36 
     37 ll d[N],mx[N],dis[N];
     38 int flag[N],size[N],fa[N],b[N],q[N];
     39 vector<node>c[N];
     40 
     41 void dfs(int u)
     42 {
     43     flag[u]=1; 
     44     for(int i=0;i<=(int)c[u].size()-1;i++)
     45     {
     46         int v=c[u][i].x;
     47         if(!flag[v])
     48         {
     49              fa[v]=u;
     50              dis[v]=dis[u]+c[u][i].cost;
     51              dfs(v);
     52         }
     53     }
     54 }
     55 
     56 void dfs2(int u)
     57 {
     58     flag[u]=size[u]=1;
     59     mx[u]=dis[u];
     60     for(int i=0;i<=(int)c[u].size()-1;i++)
     61     {
     62         int v=c[u][i].x;
     63         if(flag[v]==0&&b[v]==0)
     64         {
     65             dfs2(v);
     66             size[u]+=size[v];
     67             mx[u]=max(mx[u],mx[v]);
     68         } 
     69     }
     70 }
     71 
     72 int main()
     73 { 
     74      int n,m;
     75     scanf("%d%d",&n,&m);
     76     for(int i=1;i<=n;i++) c[i].clear();
     77     for(int i=1;i<=n-1;i++)
     78     {
     79         int x,y,z;
     80         scanf("%d%d%d",&x,&y,&z);
     81         c[x].push_back(node(y,z)); 
     82         c[y].push_back(node(x,z));
     83     }
     84     memset(flag,0,sizeof(flag));
     85     dis[0]=0;
     86     dfs(1);
     87     memset(b,0,sizeof(b)); 
     88     int num=0;
     89     int k=n;
     90     while(k!=1)
     91     {
     92         q[++num]=k;
     93         b[k]=1;
     94         k=fa[k];
     95     }
     96     q[++num]=1; b[1]=1;
     97     memset(flag,0,sizeof(flag));
     98     for(int i=1;i<=num;i++) dfs2(q[i]);
     99 
    100     int p=0;
    101     for(int i=1;i<=num;i++) 
    102     {
    103         int u=q[i];
    104          if(size[u]>=3){p=1; break;}
    105     }
    106     
    107     for(int i=1;i<=num/2;i++) swap(q[i],q[num-i+1]);
    108     ll len=-oo;
    109     for(int i=1;i<=num;i++)
    110     {
    111         int u=q[i];
    112         if(i>=2)
    113         {
    114             int fa=q[i-1];
    115             if(mx[u]>dis[u]) len=max(len,mx[u]-dis[u]*2+d[i-1]);
    116              else
    117              {
    118                  if(mx[fa]>dis[fa]) len=max(len,mx[u]-dis[u]*2+d[i-1]);
    119                   else if(i>=3)
    120                   {
    121                       int x=q[i-2];
    122                       len=max(len,mx[u]-dis[u]*2+d[i-2]);
    123                   } 
    124              }
    125         }
    126         if(i==1) d[i]=mx[u];
    127          else d[i]=max(d[i-1],mx[u]);
    128     }
    129     
    130     for(int i=1;i<=m;i++)
    131     {
    132         int x;
    133         scanf("%d",&x);
    134         if(p){printf("%lld
    ",dis[n]); continue;}
    135         printf("%lld
    ",min(dis[n],dis[n]+len+x));
    136     }
    137     return 0;
    138 }
  • 相关阅读:
    3步轻松搞定Spring Boot缓存
    备战“金九银十”10道String高频面试题解析
    ConcurrentHashMap比其他并发集合的安全效率要高一些?
    3年java开发竟然还不知道Lambda的这个坑
    5分钟搞清楚Synchronized和Lock的概念与区别
    3年Java开发都知道的Redis数据结构和通用命令
    8月份21道最新Java面试题剖析(数据库+JVM+微服务+高并发)
    35个Java代码优化的细节,你知道几个?
    vba里面打开word文档,并实现通过特殊的字符将文档中的字符实现切分
    通过vba实现替换word里面指定的字符的方法
  • 原文地址:https://www.cnblogs.com/myx12345/p/10065082.html
Copyright © 2020-2023  润新知