HDU 5886 Tower Defence
树的直径。
比赛的时候想着先树$dp$处理子树上的最长链和次长链,然后再从上到下进行一次$dfs$统计答案,和$CCPC$网络赛那个树$dp$一样,肯定是可以写的,但会很烦.......后来写崩了。
然后有一种新思路,很容易写。
假设下图中红线是树的直径,圆圈是直径上的节点,黑线表示一颗树。
如果删除的边不在直径上,那么删除这条边的答案就是直径长度。
如果删除的边在直径上,也就把下面的图分成了两半,左边和右边。
左边最大值会在什么情况下产生?
必然是$A->B->C$这样的情况产生的。不可能是从$D$到$C$这样的路径产生,因为$D->E$的长度最长只可能是$A->D$的长度。
右边部分最大值产生的情况也是一样的。
所以只要递推一下就可以了。

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
#include<map>
#include<set>
#include<queue>
#include<stack>
#include<bitset>
#include<iostream>
using namespace std;
typedef long long LL;
const double pi=acos(-1.0),eps=1e-;
void File()
{
freopen("D:\\in.txt","r",stdin);
freopen("D:\\out.txt","w",stdout);
}
template <class T>
inline void read(T &x)
{
char c=getchar(); x=;
while(!isdigit(c)) c=getchar();
while(isdigit(c)) {x=x*+c-''; c=getchar();}
} const int maxn=;
int T,n,h[maxn],sz,mx,p1,p2,ll;
int path[maxn],tmp[maxn],cnt,ans[maxn];
struct Edge{int u,v,w,nx;}e[*maxn];
int M[maxn];
bool f[maxn],g[maxn];
int P[maxn],Q[maxn],li[maxn],num; void add(int a,int b,int c)
{
e[sz].u=a; e[sz].v=b; e[sz].w=c;
e[sz].nx=h[a]; h[a]=sz++;
} void dfs(int x,int dep,int len,bool d)
{
f[x]=;
if(len>mx)
{
if(d==) mx=len,p1=x;
else
{
mx=len,p2=x,cnt=dep;
for(int i=;i<cnt;i++) path[i]=tmp[i];
}
}
for(int i=h[x];i!=-;i=e[i].nx)
{
if(f[e[i].v]) continue;
tmp[dep]=i;
dfs(e[i].v,dep+,len+e[i].w,d);
}
} void Find(int x,int len)
{
g[x]=; if(len>ll) ll=len;
for(int i=h[x];i!=-;i=e[i].nx)
{
if(f[i/]) continue;
if(g[e[i].v]) continue;
Find(e[i].v,len+e[i].w);
}
} int main()
{
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
memset(h,-,sizeof h); cnt=sz=;
for(int i=; i<n-; i++)
{
int u,v,w; scanf("%d%d%d",&u,&v,&w);
add(u,v,w); add(v,u,w);
}
memset(f,mx=,sizeof f); dfs(,,,);
memset(f,mx=,sizeof f); dfs(p1,,,); // for(int i=0;i<cnt;i++) printf("%d -> %d\n",e[path[i]].u,e[path[i]].v); memset(f,,sizeof f);
for(int i=; i<cnt; i++) f[path[i]/]=; memset(g,,sizeof g); int L=,R; for(int i=;i<cnt;i++)
{
ll=; Find(e[path[i]].v,);
M[e[path[i]].v]=ll;
} L=; P[e[path[]].u]=;
for(int i=;i<cnt;i++)
{
L=L+e[path[i]].w;
P[e[path[i]].v]=max(L+M[e[path[i]].v],P[e[path[i]].u]);
} R=; Q[e[path[cnt-]].v]=;
for(int i=cnt-;i>=;i--)
{
R=R+e[path[i]].w;
Q[e[path[i]].u]=max(R+M[e[path[i]].u],Q[e[path[i]].v]);
} for(int i=;i<cnt;i++)
{
int x1=P[e[path[i]].u],x2=Q[e[path[i]].v];
ans[path[i]/]=max(x1,x2);
} for(int i=; i<n-; i++) if(f[i]==) ans[i]=mx; LL Ans=;
for(int i=;i<n-;i++) Ans=Ans+(LL)ans[i];
printf("%lld\n",Ans);
}
return ;
}
HDU 5886 Tower Defence的更多相关文章
- 动态规划(树形DP):HDU 5886 Tower Defence
aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAA2MAAAERCAIAAAB5Jui9AAAgAElEQVR4nOy9a6wsS3YmFL/cEkh4LP
- HDU 5886 Tower Defence(2016青岛网络赛 I题,树的直径 + DP)
题目链接 2016 Qingdao Online Problem I 题意 在一棵给定的树上删掉一条边,求剩下两棵树的树的直径中较长那的那个长度的期望,答案乘上$n-1$后输出. 先把原来那棵树的 ...
- hdu 5779 Tower Defence
题意:考虑由$n$个结点构成的无向图,每条边的长度均为$1$,问有多少种构图方法使得结点$1$与任意其它节点之间的最短距离均不等于$k$(无法到达时距离等于无穷大),输出答案对$1e9+7$取模.$1 ...
- Hdu 2971 Tower
Description Alan loves to construct the towers of building bricks. His towers consist of many cuboid ...
- hdu 4779 Tower Defense (思维+组合数学)
Tower Defense Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 132768/132768 K (Java/Others) ...
- HDU5886 Tower Defence 【两遍树形dp】【最长链预处理】
题意:N个点的一棵带权树.切掉某条边的价值为切后两树直径中的最大值.求各个边切掉后的价值和(共N-1项). 解法一: 强行两遍dp,思路繁琐,维护东西较多: dis表示以i为根的子树的直径,dis2表 ...
- HDU5779 Tower Defence (BestCoder Round #85 D) 计数dp
分析(官方题解): 一点感想:(这个题是看题解并不是特别会转移,当然写完之后看起来题解说得很清晰,主要是人太弱 这个题是参考faebdc神的代码写的,说句题外话,很荣幸高中和faebdc巨一个省,虽然 ...
- hdu 4779 Tower Defense 2013杭州现场赛
/** 题意: 有两种塔,重塔,轻塔.每种塔,能攻击他所在的一行和他所在的一列, 轻塔不 能被攻击,而重塔可以被至多一个塔攻击,也就是说重塔只能被重塔攻击.在一个n*m 的矩阵中,最少放一个塔,可放多 ...
- HDU5779 Tower Defence
dp[i][j][k] 已选i个人 选到第j层 第j层有k个人 讨论相邻层 上一层选了l人 那么共有 两层之间的方案数 以及这一层自己的方案数 #include<bits/stdc++.h&g ...
随机推荐
- 【IOS开发】创建XML文件
- (void)viewDidLoad { [super viewDidLoad]; NSString *path = [[NSBundle mainBundle] pathForResource:@ ...
- RDLC(Reportview)报表直接打印,支持所有浏览器,客户可在linux下浏览使用
最近在做一个打印清单的,但是rdlc报表自带的工具栏中的打印按钮只有在ie内核下的浏览器才可以使用(其他的就会 隐藏),这导致了使用火狐和谷歌浏览器还有使用linux系统的客户打印成了问题,于是就自己 ...
- (转)C++重写、重载和重定义的区别
C++ 重写重载重定义区别 (源自:http://blog.163.com/clevertanglei900@126/blog/static/111352259201102441934870/) 1 ...
- Redis系统学习 五、管理
在最后一章里,我们将集中谈论Redis运行中的一些管理方面内容.这是一个不完整的Redis管理指南,我们将会回答一些基本的问题,初接触Redis的新用户可能会很感兴趣. 配置(Configuratio ...
- Microsoft 电信项目组 Net代码生成器1.1
Microsoft 电信项目组 Net代码生成器1.1 微软电信项目组代码生成器 为什么要使用这个代码生成器: 1.这个代码生成器采用 微软 企业库5.0 版本,目前CAPO所在的项目组都在使用这个 ...
- HDFS中文件的压缩与解压
HDFS中文件的压缩与解压 文件的压缩有两大好处:1.可以减少存储文件所需要的磁盘空间:2.可以加速数据在网络和磁盘上的传输.尤其是在处理大数据时,这两大好处是相当重要的. 下面是一个使用gzip工具 ...
- AOP之拦截函数调用链实现
AOP之拦截函数调用链实现 定义函数A,B,C,调用A->B->C,这样就形成了函数静态调用链,而AOP要做的是能动态的添加多个B,形成A->B1->B2->B3...- ...
- TCPDump 抓Loopback数据包
编写网络程序必备截包工具, unix下面自带tcpdump, linux就不用说了.用于排查网络程序的bug,命令行如何使用请百度谷歌.分析包推荐wireshark,可视化非常方便.一般都是在非Win ...
- 趋势:Chrome为打包应用提供强大新特性
Chrome 7月9日刚为Chrome打包的应用提供了强大的访问Google服务例如Google统计.GoogleAPI和Google 钱包的能力,除此之外,还能够使用系统层面的服务包括蓝牙和原生应用 ...
- Ajax实现xml文件数据插入数据库(二)--- ajax实现与jsp的数据交互。
在上一篇文章中我们成功得到了重新组织后的数据,接下来需要做的便是将数据插入到数据库中了.在与数据库打交道的过程中有一些方法是普遍的,我们将这些通用方法封装到一个DbUtil类中,以便复用,封装好的Db ...