Description

oi_juruo热爱一款名叫黑暗之魂的游戏。在这个游戏中玩家要操纵一名有 点生命值的无火的余灰在一张地图中探险。地图中有n个篝火(也就是存档点)。在篝火处休息可以将生命值恢复满。每个篝火都会向其他篝火的其中之一连有一条通道(显然,通道是双向的),这些篝火之间都相互可达。也就是说,这是一张n个点,n条边的无向连通图。每条通道里都有一些怪物,经过oi_juruo的分析,他得到了每条边的怪物会对他造成的伤害值 .为了向oier们表演他高超的游戏技巧,他要从任意一个篝火跑到任意另一个篝火而不在之间的篝火休息,在此期间,他会和他经过的通道中的怪物战斗并损失 的生命值。现在oi_juruo想知道,他的生命值 至少为多少,才能完成任意一条旅途。oi_juruo并不傻,他会走最安全的路。本题时限为3000ms

Input

第一行一个整数n。之后n行,每行三个整数ui,vi,ai ,表示有一条从ui 连向vi ,怪物伤害值为ai 的通道。

Output

一行一个数hp,表示无火的余灰的最小生命值。

Sample Input

5
1 2 2
2 3 2
3 4 2
1 4 1
4 5 4

Sample Output

8

样例说明

从2到5的路最危险,2 1 4 5受到了7点伤害,所以需要有8点生命值。

Data Constraint

思路

显然上述方法无法拓展,原因在于将环套树看成图而不是一棵略复杂的树更简单的仙人掌。环套树可以视为将森林的根摆在一个环上的产物。显然,对每棵树我们可以计算出他的内部直径,之后只有这棵树的最长链有意义。问题规约为:求一个“刺球”的直径。暴力计算是O(k2)的(枚举所有的“刺”对)可以想到,这可以使用单调队列优化,我们要维护比圆的周长的一半要小的部分中的递减序列(因为 ans=max(len[x]+pre[x]-pre[i]-len[i]),枚举右端转移即可,要注意把序列倍长。

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<algorithm>
#define ll long long
using namespace std;
const int maxn=1e6+11;
int n,cnt,k,bel,tot,head1,tail,boo,list[maxn],dfn[maxn],low[maxn],belong[maxn];
bool vis[maxn];
int root[maxn],q[maxn*2];
ll ans,f[maxn*2],len[maxn*2],pre[maxn*2],dis[maxn*2],mid;
struct E{ int v,to,from; }e[maxn*2];
struct A{ int x,y,v; }a[maxn];
vector<int>Q;
void insert(int a,int b,int c)
{ e[++cnt].to=b; e[cnt].from=list[a]; e[cnt].v=c; list[a]=cnt; e[++cnt].to=a; e[cnt].from=list[b]; e[cnt].v=c; list[b]=cnt;
}
void dfs(int x,int fa)
{ll max1=0,max2=0,l=0;for(int i=list[x]; i; i=e[i].from)if(belong[e[i].to]!=k&&e[i].to!=fa){dfs(e[i].to,x);l=f[e[i].to]+e[i].v;if(l>max1) max2=max1,max1=l; else max2=max(l,max2);}ans=max(max1+max2,ans);f[x]=max1;
}
void tarjan(int x,int fa)
{dfn[x]=low[x]=++cnt,vis[x]=1;Q.push_back(x);for(int i=list[x]; i; i=e[i].from)if(e[i].to!=fa) {if(!dfn[e[i].to]){tarjan(e[i].to,x);low[x]=min(low[x],low[e[i].to]);}else if(vis[e[i].to]) low[x]=min(low[x],dfn[e[i].to]);}if(low[x]==dfn[x]){bel++;int y=0,boo=0;if(Q.back()!=x) boo=1,k=bel;while(y!=x){y=Q.back(),Q.pop_back();belong[y]=bel,vis[y]=0;if(boo) root[++tot]=y;}}
}
bool cmp(A a,A b)
{return a.x==b.x?(a.y==b.y?a.v<b.v:a.y<b.y):a.x<b.x;
}
int main()
{freopen("darksoul.in","r",stdin); freopen("darksoul.out","w",stdout);scanf("%d",&n);for(int i=1; i<=n; i++) {scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].v);if(a[i].x>a[i].y) swap(a[i].x,a[i].y);}sort(a+1,a+n+1,cmp);bool boo=false;for(int i=1; i<=n; i++)if(a[i].x==a[i].y||a[i].x==a[i-1].x&&a[i].y==a[i-1].y) boo=true;else insert(a[i].x,a[i].y,a[i].v);if(boo){k=-1,dfs(1,0),printf("%lld",ans+1);return 0;}cnt=0,tarjan(1,0);for(int i=1; i<=tot; i++) dfs(root[i],0),len[i]=f[root[i]];for(int i=1; i<=tot; i++) for(int j=list[root[i]]; j; j=e[j].from) if(e[j].to==root[i!=1?i-1:tot]){dis[i]=(ll)e[j].v;break;}for(int i=1; i<=tot; i++) dis[i+tot]=dis[i],len[i+tot]=len[i];for(int i=1; i<=tot*2; i++) pre[i]=pre[i-1]+dis[i];mid=pre[tot];head1=tail=q[head1]=1;for(int i=2; i<=2*tot; i++){while(head1<=tail&&(pre[i]-pre[q[head1]]>mid/2)) head1++;if(head1<=tail) ans=max(ans,len[q[head1]]+len[i]+pre[i]-pre[q[head1]]);while(head1<=tail&&(len[i]-pre[i]>=len[q[tail]]-pre[q[tail]])) tail--;q[++tail]=i;}printf("%lld",ans+1);
}

【JZOJ A组】黑暗之魂(darksoul)相关推荐

  1. JZOJ 5905. 【NOIP2018模拟10.15】黑暗之魂(darksoul)

    Description oi_juruo热爱一款名叫黑暗之魂的游戏.在这个游戏中玩家要操纵一名有 点生命值的无火的余灰在一张地图中探险.地图中有n个篝火(也就是存档点).在篝火处休息可以将生命值恢复满 ...

  2. [树上最长链][tarjan][单调队列][环上前缀和] Jzoj P5905 黑暗之魂(darksoul)

    Description oi_juruo热爱一款名叫黑暗之魂的游戏.在这个游戏中玩家要操纵一名有 点生命值的无火的余灰在一张地图中探险.地图中有n个篝火(也就是存档点).在篝火处休息可以将生命值恢复满 ...

  3. jzoj C组 2017.1.19 比赛

    第一题--小x的游戏 题目描述 Tac游戏在一个4*4的方格上进行.起先可能会在16个方格中出现一个标记'T',其余的方格是空着的.游戏有两个玩家,小x和小o.小x先开始,然后游戏轮流进行.每一步玩家 ...

  4. 【JZOJ A组】海明距离

    Description 对于二进制串a,b,他们之间的海明距离是指两个串异或之后串中1的个数.异或的规则为: 0 XOR 0 = 0 1 XOR 0 = 1 0 XOR 1 = 1 1 XOR 1 = ...

  5. 【JZOJ A组】昆特牌

    Description 作为一个资深OIer,你被邀请到位于波兰的CDPR总部参观.但没想到你刚一到就遇到了麻烦.昆特牌的数据库发生了故障.原本昆特牌中有 k种卡牌和n 种阵营,为了平衡,每个阵营拥有 ...

  6. 【JZOJ B组】【JSOI2013】吃货JYY

    Description 世界上一共有N个JYY愿意去的城市,分别从1编号到N.JYY选出了K个他一定要乘坐的航班.除此之外,还有M个JYY没有特别的偏好,可以乘坐也可以不乘坐的航班. 一个航班我们用一 ...

  7. 【JZOJ A组】排列

    Description 一个关于n个元素的排列是指一个从{1, 2, -, n}到{1, 2, -, n}的一一映射的函数.这个排列p的秩是指最小的k,使得对于所有的i = 1, 2, -, n,都有 ...

  8. 【JZOJ A组省选】词典

    Description Input 第一行两个数n,m,表示有n个字符串,m个询问. 接下来n行,每行一个字符串Ti . 再接下来m行,每行一个字符串Si . Output 对于每个询问,输出一个an ...

  9. JZOJ B组【GDKOI2014】壕壕的寒假作业

    题目: Input Output 输出n行.第i行输出两个整数,分别表示第i份作业最早完成的时刻以及最晚完成的时刻,两个整数之间以一个空格间隔. Sample Input 4 4 3 4 5 6 1 ...

最新文章

  1. Texmaker使用方法、Latex的优缺点
  2. Ubuntu安装vmtools
  3. 650c公路车推荐_盘点2020年各价位高性价比入门公路车
  4. 如何在IDEA中创建并部署JavaWeb程序
  5. java strim性能_Java代码性能优化总结
  6. 用python分析拼多多_利用Python分析拼多多上卖的最热的产品, 结果出乎大多数人意料!...
  7. Windows环境下安装Hadoop+Hive的使用案例
  8. Solidworks 课程大纲(虎课网)
  9. tensorflow dataset 用法 from_tensor_slices dataset.repeat dataset.batch dataset.shuffle
  10. 计算机课说话检查200字,上课说话检讨书200字(精选10篇)
  11. “NODE星球”空降格尔木,首创沉浸体验式戈壁嘉年华颠覆想象
  12. 一个全国500强企业的老板是如何关爱员工的
  13. csv文件中文乱码转换
  14. 一种基于多维时序数据预测综合判定的方法(内存告警)
  15. 小黄图升级了,接入更加强大的鉴黄功能
  16. 动态链接(地址无关技术)
  17. LWN:在进程级别完成内核相同页面合并(KSM)控制!
  18. 2018年固态硬盘会大规模降价吗?
  19. 探讨降低城市污水厂电气能耗的对策研究
  20. android mac 照片恢复,相片恢复?误删的手机照片简单的找回方法来了!

热门文章

  1. 移动网关贝尔G-140W-C 修改wifi前缀去掉CMCC
  2. python聊天智能回复_【微信】设置自动回复消息和智能聊天
  3. Android四大组件-Boardcast
  4. 最简单的内网穿透教程
  5. Homebridge插件编写-基于homebridge-aqara
  6. Apache Dubbo官网推荐使用建议
  7. mx250显卡天梯图_MX250和150差别大吗?MX250和MX150区别对比 (全文)
  8. JS遍历(循环)——JS对象遍历(循环)JS数组遍历(循环)
  9. 微信小程序 scroll-view详解
  10. 【硬核干货】Teleport Ultra扒站教程 (附汉化破解版资源下载链接)