2016暑期集训16C星座
来源:互联网 发布:苏宁易购客服软件 编辑:程序博客网 时间:2024/05/07 01:20
星座
星空中有n颗星星,有n-1对星星间被人为地连上了线,每条连线有各自的长度。所有星星被连成了一个整体。现在,你要在星系中找到一个最大的十字形星座。即,你要找到两条星星构成的路径,使得它们恰好有一颗公共星(这颗公共星不能是某条路径的端点),且两条路径的长度和最大。
左图红线表示了一个合法的十字形星座,而右图的星座并不合法。
输入
第一行一个数n,表示星星的数量。
接下来n行,每行3个数x,y,z,表示第x颗星星和第y颗星星间有一条连线,它的长度是z。
输出
一行,包含一个整数,表示最大的路径长度和。若答案不存在,输出-1。
样例输入
10
3 8 6
9 3 5
1 9 2
4 8 6
2 3 3
10 4 8
5 9 5
7 2 3
6 9 1
样例输出
33
提示
20%的数据n<=1000
50%的数据n<=10,000
100%的数据n<=100,000,0<=z<=1000
其实自己静下来做一做还是简单的
这里的f与g数组十分jingmiao
20% 枚举公共点,求出它每个出度方向上到其它点的最长路径长度,取前4长的加起来。
50% 其实暴力是能过50%的数据的,只要在枚举公共点时先判断一下出度是否大于4即可。这是为了告诉大家就算写暴力也要把必要的优化加上。
100% 任选一个树根,DP,f[i,0..3]分别表示从i开始,向下走到某个叶子为止最长、第二长、第三长、第四长的路径长度。从叶子向树根的顺序DP,每次用f[i,0]去尝试更新i的父亲,可以很方便地求出f数组。用g[i]表示以i为起点,第一步向i的父亲方向走的最长路径长度。第一步从i走到i的父亲fa[i]后,第二步有两种选择, 第一种是继续往父亲走,则最长长度为g[fa[i]],第二种是向下走。为了使路径最长 首选当然是f[fa[i],0],但如果i处在f[fa[i],0]对应的那条路径上,那就只能选择f[fa[i],1]了。有了f数组和g数组后,枚举公共点i,答案为max{f[i,0]+f[i,1]+f[i,2]+f[i,3] , g[i]+f[i,0]+f[i,1]+f[i,2]}。
#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>#define ll long longusing namespace std;int n,tot,ans,du[100005];int Next[200005],head[100005],to[200005],len[200005];int f[100005][4],g[100005],b[100005];void add(int x,int y,int z){ Next[tot]=head[x]; to[tot]=y; len[tot]=z; head[x]=tot++;}void dfs(int x,int pre){ for (int i=head[x];i!=-1;i=Next[i]) { int y=to[i],z=len[i]; if (y==pre) continue; dfs(y,x); if (f[y][0]+z>=f[x][0]) { f[x][3]=f[x][2]; f[x][2]=f[x][1]; f[x][1]=f[x][0]; f[x][0]=f[y][0]+z; b[x]=y; } else if (f[y][0]+z<f[x][0] && f[y][0]+z>=f[x][1]) { f[x][3]=f[x][2]; f[x][2]=f[x][1]; f[x][1]=f[y][0]+z; } else if (f[y][0]+z<f[x][1] && f[y][0]+z>=f[x][2]) { f[x][3]=f[x][2]; f[x][2]=f[y][0]+z; } else if (f[y][0]+z>=f[x][3]) f[x][3]=f[y][0]+z; }}void dfs2(int x,int pre){ for (int i=head[x];i!=-1;i=Next[i]) { int y=to[i],z=len[i]; if (y==pre) continue; if (b[x]==y) g[y]=max(g[x],f[x][1])+z; else g[y]=max(g[x],f[x][0])+z; dfs2(y,x); }}int main(){ scanf("%d",&n); for (int i=1;i<=n;i++) head[i]=-1; for (int i=1;i<n;i++) { int x,y,z; scanf("%d%d%d",&x,&y,&z); du[x]++; du[y]++; add(x,y,z); add(y,x,z); } dfs(1,-1); dfs2(1,-1); for (int i=1;i<=n;i++) if (du[i]>=4) { ans=max(ans,max(f[i][0]+f[i][1]+f[i][2]+f[i][3],g[i]+f[i][0]+f[i][1]+f[i][2])); } printf("%d\n",ans); return 0;}
- 2016暑期集训16C星座
- 2016暑期集训1C 最长回文
- 2016暑期集训11C hdu5714 拍照
- 2016暑期集训16A强迫症
- 2016暑期集训16B手套
- 2016暑期集训---周赛(水题)
- 暑期集训
- 2016暑期集训10 C吴传之火烧连营
- 2016暑期集训12C L国货物运输 HDU 5699货物运输
- poj2287 Tian Ji -- The Horse Racing(2016xynu暑期集训检测 -----C题)
- xjtu暑期集训2016-7-9 题解
- 2016暑期集训---搜索(整数拆分)
- 2016暑期集训---搜索(简单BFS)
- 2016暑期集训---搜索(简单BFS)
- 2016暑期集训1A 组合数
- 2016暑期集训14A找朋友
- HPU2017-2016级暑期集训练习赛
- HPU2017-2016级暑期集训练习赛
- 孤儿进程和僵尸进程的区别
- zookeeper客户端curator使用手记
- HTML+CSS学习笔记 (三)
- 2016-08-23-java-基于socket和多线程的聊天器通讯
- leetcode: Combination Sum III
- 2016暑期集训16C星座
- android中使用SharedPreferences进行数据存储的操作方法
- 石子合并问题
- h5学习笔记: 导航菜单(2)
- nginx 代理配置文件
- Oracle知识点总结
- Android自定义通知样式适配
- Android开源控件viewbadger的原理及使用
- poj2975 Nim博弈好题