题意:给你一棵n 个节点的树,定义1到n的代价是1到 n节点间的最短路径的长度。
现在给你 m 组询问,让你添加一条边权为 w 的边(不与原图重复),求代价的最大值。询问之间相互独立。
1≤n,m≤3×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 }