【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\n",dis[n]); continue;}
135         printf("%lld\n",min(dis[n],dis[n]+len+x));
136     }
137     return 0;
138 }

 

posted on 2018-12-04 16:48  myx12345  阅读(242)  评论(0编辑  收藏  举报

导航