HDU 5886 Tower Defence (最长链预处理)
2016-09-18 10:22
281 查看
题意:给出一棵树,边上有权值,现在毁掉任意一条边,分成两部分,求这两部分中最远的两点距离期望,答案*(n-1)
分析:
说白了就是求最远距离加成和
对于一棵树来说,两点最远的距离,考虑两点:
1.最长链没有被拆开,那么答案就是最长链;
2.最长链被拆开了,那么答案一定在最长链的端点到某个叶子结点上;
证明略。
有了这个结论,这个题就好做了,首先预处理出最长链,数组存下来,然后对于每个最长链上的结点预处理出它的权值最大的叶子结点(不在最长链上),剩下的就是处理最长链左边和右边的拆开后的最大值了,左右扫一遍,两个数组LR存下来,最后On扫一遍最长链,取LR中最大值得到答案。
复杂度On
比赛写的急,代码有些挫
分析:
说白了就是求最远距离加成和
对于一棵树来说,两点最远的距离,考虑两点:
1.最长链没有被拆开,那么答案就是最长链;
2.最长链被拆开了,那么答案一定在最长链的端点到某个叶子结点上;
证明略。
有了这个结论,这个题就好做了,首先预处理出最长链,数组存下来,然后对于每个最长链上的结点预处理出它的权值最大的叶子结点(不在最长链上),剩下的就是处理最长链左边和右边的拆开后的最大值了,左右扫一遍,两个数组LR存下来,最后On扫一遍最长链,取LR中最大值得到答案。
复杂度On
比赛写的急,代码有些挫
#include<cstring> #include<string> #include<iostream> #include<queue> #include<cstdio> #include<algorithm> #include<map> #include<cstdlib> #include<cmath> #include<vector> //#pragma comment(linker, "/STACK:1024000000,1024000000"); using namespace std; #define INF 0x3f3f3f3f #define maxn 200014 long long L[maxn],R[maxn]; int fir[maxn],nex[maxn],v[maxn],w[maxn],e_max; int p[maxn],len,vis[maxn]; long long cost[maxn],cost1[maxn]; void init() { len=0; memset(L,0,sizeof L); memset(R,0,sizeof R); memset(cost,0,sizeof cost); memset(cost1,0,sizeof cost1); memset(vis,0,sizeof vis); memset(fir,-1,sizeof fir); e_max=0; } void add_edge(int s,int t,int c) { int e=e_max++; v[e]=t; w[e]=c; nex[e]=fir[s]; fir[s]=e; } int temp,add; void dfs1(int k,long long sum,int pre) { if(sum>add) temp=k,add=sum; for(int i=fir[k];~i;i=nex[i]) { int e=v[i]; if(e==pre) continue; dfs1(e,sum+w[i],k); } } int ok; int dfs2(int s,int t,int pre,long long sum) { if(s==t) { ok=1; return t; } for(int i=fir[s];~i;i=nex[i]) { int e=v[i]; if(e==pre) continue; int tag=dfs2(e,t,s,sum+w[i]); if(ok) { vis[tag]=1; cost[len]=sum+w[i]; p[len++]=tag; return s; } } return s; } long long dfs3(int k,int pre) { long long mx=0; for(int i=fir[k];~i;i=nex[i]) { int e=v[i]; if(vis[e]||e==pre) continue; mx=max(mx,dfs3(e,k)+w[i]); } return mx; } int main() { int T; scanf("%d",&T); while(T--) { init(); int n; scanf("%d",&n); for(int i=1;i<n;i++) { int a,b,w; scanf("%d%d%d",&a,&b,&w); add_edge(a,b,w); add_edge(b,a,w); } add=0;dfs1(1,0,-1); int s=temp; add=0;dfs1(s,0,-1); int t=temp; long long sd=add; long long ans=0; ok=0; dfs2(s,t,-1,0); p[len++]=s; vis[s]=1; for(int i=1;i<len-1;i++) { cost1[i]=dfs3(p[i],-1); } ans+=sd*(n-len); long long temp=0,ss=0; for(int i=0;i<len;i++) { L[i]=max(sd-cost[i]+cost1[i],temp); temp=max(L[i],temp); } temp=0; for(int i=len-1;i>=0;i--) { R[i]=max(cost[i]+cost1[i],temp); temp=max(R[i],temp); } for(int i=0;i<len-1;i++) { ans+=max(L[i],R[i+1]); } printf("%I64d\n",ans); } return 0; }
相关文章推荐
- HDU 5886 Tower Defence
- Hdu-5886 Tower Defence(树形DP)
- HDU 5886 Tower Defence(树形dp|树的直径)
- HDU-5886-Tower Defence
- 【HDU 5886】Tower Defence(树的直径+树形DP)
- HDU5886 Tower Defence 【两遍树形dp】【最长链预处理】
- hdu 5886 Tower Defence(树形dp)
- HDU 5886 - Tower Defence(最短路+最小割)
- hdu 5886 Tower Defence 2016ACM/ICPC青岛赛区网络赛1009
- [HDU 5886] Tower Defence (树形DP)
- hdu 5886 Tower Defence 树形期望dp 雪漫防守战
- HDU - 4778 Gems Fight! 博弈+状压预处理+记忆化搜索 好题!
- hdu 5106 组合数预处理
- HDU 4261 Estimation(set预处理中位数+dp+缺页中断t个爽)
- HDU 4284 Travel (Folyd预处理+dfs暴搜)
- HDU 4436 str2int 后缀数组(前缀和预处理)
- HDU 3533 Escape (bfs + 预处理 + 剪枝)
- HDU 5439 Aggregated Counting(找规律+预处理)
- hdu 5439 Aggregated Counting 2015长春网络赛 分块 二分 预处理