【HDU 5886】Tower Defence(树的直径+树形DP)
来源:互联网 发布:报告式资产负债表 知乎 编辑:程序博客网 时间:2024/05/17 00:50
【HDU 5886】Tower Defence(树的直径+树形DP)
题目大意:
带边权的树,随机删掉一条边,保留剩下两棵树中较大的中线。
求删除一条边后中线大小的期望*(n-1)
说白了就是统计删除每条边的情况下两棵树较大的中线,求个和。
对于原树,两次dfs可以找出来中线,同时可以标记中线上的点。
那么对于任何一条边
如果两个点都在中线上,呢么就要对于两个新生成的树分别求中线取最大。
对于原树中线两端为
这样查询的时候 判断一下u,v分别相对a,b的距离(也就是深度)
搞清楚切割后两颗树谁是相对于a的子树,谁是相对于b的子树。
取个最大即可。
代码如下:
#include <iostream>#include <cmath>#include <vector>#include <cstdlib>#include <cstdio>#include <climits>#include <ctime>#include <cstring>#include <queue>#include <stack>#include <list>#include <algorithm>#include <map>#include <set>#define LL long long#define Pr pair<int,int>#define fread(ch) freopen(ch,"r",stdin)#define fwrite(ch) freopen(ch,"w",stdout)using namespace std;const int INF = 0x3f3f3f3f;const int msz = 10000;const int mod = 1e9+7;const double eps = 1e-8;const int maxn = 100010;struct Edge{ int v,w,next;} eg[maxn<<1]; bool vis[maxn],on[maxn];int dis[maxn],cost[2][3][maxn],depth[2][maxn];int head[maxn];int tp;int n;void Add(int u,int v,int w){ eg[tp].v = v; eg[tp].w = w; eg[tp].next = head[u]; head[u] = tp++;}void dfs1(int u,int pre){ int v,w; for(int i = head[u]; i != -1; i = eg[i].next) { v = eg[i].v; w = eg[i].w; if(v == pre) continue; dis[v] = dis[u] + w; dfs1(v,u); }}int st,en;bool dfs2(int u,int pre){ int v; on[u] = u==en; for(int i = head[u]; i != -1; i = eg[i].next) { v = eg[i].v; if(v == pre) continue; if(dfs2(v,u)) on[u] = 1; } return on[u];}void dfs3(int pos,int u,int pre,int dep){ depth[pos][u] = dep; cost[pos][0][u] = cost[pos][1][u] = cost[pos][2][u] = 0; int v,w; for(int i = head[u]; i != -1; i = eg[i].next) { v = eg[i].v; w = eg[i].w; if(v == pre) continue; dfs3(pos,v,u,dep+1); int tmp = cost[pos][1][v]+w; if(tmp > cost[pos][1][u]) { cost[pos][2][u] = cost[pos][1][u]; cost[pos][1][u] = tmp; } else if(tmp > cost[pos][2][u]) cost[pos][2][u] = tmp; cost[pos][0][u] = max(cost[pos][0][u],cost[pos][0][v]); } cost[pos][0][u] = max(cost[pos][0][u],cost[pos][1][u]+cost[pos][2][u]);}void init(){ dis[1] = 0; dfs1(1,1); st = 1; for(int i = 1; i <= n; ++i) if(dis[i] > dis[st]) st = i; dis[st] = 0; memset(on,0,sizeof(on)); dfs1(st,st); en = 1; for(int i = 1; i <= n; ++i) if(dis[i] > dis[en]) en = i; dfs2(st,st); dfs3(0,st,st,0); dfs3(1,en,en,0);}int cal(int u,int v){ if(!on[u] || !on[v]) return dis[en]; if(depth[0][u] > depth[0][v]) { return max(cost[0][0][u],cost[1][0][v]); } return max(cost[0][0][v],cost[1][0][u]);}int main(){ //fread(""); //fwrite(""); int t,u,v,w; scanf("%d",&t); while(t--) { memset(head,-1,sizeof(head)); tp = 0; scanf("%d",&n); for(int i = 1; i < n; ++i) { scanf("%d%d%d",&u,&v,&w); Add(u,v,w); Add(v,u,w); } init(); LL ans = 0; for(u = 1; u <= n; ++u) for(int i = head[u]; i != -1; i = eg[i].next) { ans += cal(u,eg[i].v); } printf("%lld\n",ans/2); } return 0;}
0 0
- 【HDU 5886】Tower Defence(树的直径+树形DP)
- HDU 5886 Tower Defence(树形dp|树的直径)
- [HDU 5886] Tower Defence (树形DP)
- hdu 5886 Tower Defence(树形dp)
- Hdu-5886 Tower Defence(树形DP)
- hdu 5886 Tower Defence 树形期望dp 雪漫防守战
- HDU-5886-Tower Defence
- hdu 4607 树形dp 树的直径
- HDU 5779 Tower Defence(dp+组合数)
- HDU 5779 Tower Defence(Dp + 组合)
- hdu5886Tower Defence(树形dp)
- hdu 4679 Terrorist’s destroy ( 树形dp 树的直径 )
- Hdu 2196 Computer (树的直径 或 树形DP)
- hdu 2196 Computer 树形DP或者树的直径
- HDU 5886 Tower Defence (最长链预处理)
- HDU 5779 Tower Defence
- HDU 5779 Tower Defence(????)
- HDU 4612 and 4607 (tarjan求桥+树形dp求树的直径)
- hdu5898 沈阳网络赛1007
- HDU2089-不要62
- 20 ViewPager Demo4自动轮播
- java程序设计之集合中的泛型的应用
- poj1160 Post Office 四边形不等式优化
- 【HDU 5886】Tower Defence(树的直径+树形DP)
- HDU 5895&&2016 ACM/ICPC Asia Regional Shenyang Online1004 Mathematician QSC [矩阵加速+欧拉降幂]【数论】
- oncreate中对TabItem初始化失败 空指针
- 素数算法
- LeetCode-Merge Two Sorted Lists
- 地理数据结构与组织
- 【动态规划练习题】 学生宿舍(重庆一中高2018级信息学竞赛测验10) 解题报告
- LA 3644并查集
- tomcat报错catalina.sh: line 401: /usr/java/jdk1.7.52/bin/java: No such file or directory