题目链接:

http://172.16.0.132/senior/#main/show/5905

题目:

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

题目大意:

给出一棵基环树,定义任意两点之间的距离为两点之间的最短路径,最大距离为多少

题解:

分别考虑环上的每一个点

显然我们首先要找到环,考虑用类似拓扑排序的做法,即每次找度数为1的叶子节点不断向上更新,最后环上的点的度数一定为2

$f[x]$表示以$x$为根的子树中的直径,可以在拓扑排序的过程中处理出

我们已知以环上每一个点为根节点的子树的直径,问题转化成了给出一个环,环上的每一个点有一个点权,点与点之间有边权,设$dis[i][j]$为环上两点$i,j$的距离(最短路径),要计算最大的$f[i]+f[j]+dis[i][j]$

由于只能走最短路径,显然$dis[i]][j]$小于等于环的周长$S$的二分之一。我们断环成链,在可行区间范围内维护单调队列。

具体实现是令$a[i]$为节点$i$的点权,$b[i]$为链开头到节点i的路径前缀和,对于每个$i$,答案就是$a[i]+a[j]+b[i]-b[j](b[i]-b[j]<=\frac{S}{2})$取最大值,显然满足决策单调性

#include<algorithm>
#include<cstring>
#include<cstdio>
#include<iostream>
#include<queue>
#include<vector>
using namespace std;
typedef long long ll; const int N=1e6+;
int n,tot;
ll ans;
int head[N],in[N],tmp[N],qq[N];
ll f[N],dis[N],b[N],a[N];
struct EDGE
{
int to,nxt;
ll w;
}edge[N<<];
inline ll read()
{
char ch=getchar();
ll s=,f=;
while (ch<''||ch>'') {if (ch=='-') f=-;ch=getchar();}
while (ch>=''&&ch<='') {s=(s<<)+(s<<)+ch-'';ch=getchar();}
return s*f;
}
void add(int u,int v,ll w)
{
edge[++tot]=(EDGE){v,head[u],w};
head[u]=tot;
}
void topsort()
{
queue<int> q;
for (int i=;i<=n;i++) if (in[i]==) q.push(i);
while (!q.empty())
{
int k=q.front();q.pop();
for (int i=head[k];i;i=edge[i].nxt)
{
int y=edge[i].to;
if (in[y]==) continue;
ans=max(ans,f[k]+f[y]+edge[i].w);
f[y]=max(f[y],f[k]+edge[i].w);
if ((--in[y])==) q.push(y);
}
}
}
void dp(int x)
{
int t=,y=x,pp;
ll len,S=;
do
{
a[++t]=f[y];
tmp[y]=;
for(pp=head[y];pp;pp=edge[pp].nxt)
if(!tmp[edge[pp].to]&&in[edge[pp].to]==)
{
y=edge[pp].to;
b[t+]=b[t]+edge[pp].w;
break;
}
}while(pp); if (t==) return; if (t==)
{
for (int i=head[y];i;i=edge[i].nxt)
{
if (edge[i].to==x) {len=edge[i].w;break;}
}
ans=max(ans,f[x]+f[y]+len);
return;
} for (int i=head[y];i;i=edge[i].nxt)
{
if (edge[i].to==x)
{
S=b[t]+edge[i].w;
b[t+]=b[t]+edge[i].w;
}
}
for (int i=;i<t;i++) a[i+t]=a[i],b[t+i]=b[t+]+b[i];
int l=,r=;
qq[l]=;
for (int i=;i<*t;i++)
{
while (l<=r&&(b[i]-b[qq[l]]>S/||i-qq[l]>=t)) l++;
if (l<=r) ans=max(ans,b[i]-b[qq[l]]+a[qq[l]]+a[i]);
while (l<=r&&a[qq[r]]-b[qq[r]]<=a[i]-b[i]) r--;
qq[++r]=i;
}
}
int main()
{
freopen("darksoul.in","r",stdin);
freopen("darksoul.out","w",stdout);
n=read();
for (int i=,u,v,w;i<=n;i++)
{
u=read();v=read();w=read();
in[u]++;in[v]++;
if (u==v) continue;
add(u,v,w);add(v,u,w);
}
topsort();
for (int i=;i<=n;i++)
{
if (in[i]==)
{
dp(i);
break;
}
}
printf("%lld\n",ans+);
return ;
}

[JZOJ 5905] [NOIP2018模拟10.15] 黑暗之魂(darksoul) 解题报告 (拓扑排序+单调队列+无向图基环树)的更多相关文章

  1. [NOIP2015模拟10.27] 挑竹签 解题报告(拓扑排序)

    Description 挑竹签——小时候的游戏夏夜,早苗和诹访子在月光下玩起了挑竹签这一经典的游戏.挑竹签,就是在桌上摆上一把竹签,每次从最上层挑走一根竹签.如果动了其他的竹签,就要换对手来挑.在所有 ...

  2. [JZOJ 5893] [NOIP2018模拟10.4] 括号序列 解题报告 (Hash+栈+map)

    题目链接: https://jzoj.net/senior/#main/show/5893 题目: 题解: 考虑暴力怎么做,我们枚举左端点,维护一个栈,依次加入元素,与栈顶元素和栈内第二个元素相同时弹 ...

  3. [jzoj 5930] [NOIP2018模拟10.26】山花 解题报告 (质因数分类)

    题目链接: http://172.16.0.132/senior/#contest/show/2538/2 题目: 小S决定从某一个节点$u$开始对其子树中与$u$距离小于$K$的节点代表的花树进行采 ...

  4. [JZOJ 5906] [NOIP2018模拟10.15] 传送门 解题报告(树形DP)

    题目链接: https://jzoj.net/senior/#contest/show/2528/2 题目: 8102年,Normalgod在GLaDOS的帮助下,研制出了传送枪.但GLaDOS想把传 ...

  5. [JZOJ 5885] [NOIP2018模拟9.27] 物理实验 解题报告 (思维)

    题目链接: https://jzoj.net/senior/#main/show/5885 题目: 题解: 把$a$数组按升序排序 我们可以枚举$x$,发现对于任意$x$,最优情况下$y$一定等于$x ...

  6. [JZOJ 5888] [NOIP2018模拟9.29] GCD生成树 解题报告 (最大生成树+公约数)

    题目链接: http://172.16.0.132/senior/#main/show/5888 题目: 题解: 思路是这样的:两个数的最大公约数一定不会比这两个数的任意一个数大.因此我们把权值相等的 ...

  7. [NOIP2018模拟10.15]比赛报告

    闲扯 昨晚又颓到好晚,Yali的降智光环感觉持续至今... 题面好评 T1T3都玩过 逃) T1没看多久就开始写二分+并查集 然后T3看着眼熟想了一个多小时...结果啥都没想出来 赶紧看T2发现还是没 ...

  8. [jzoj 5926] [NOIP2018模拟10.25] naive 的图 解题报告(kruskal重构树+二维数点)

    题目链接: https://jzoj.net/senior/#main/show/5926 题目: 题解: 显然最小的最大路径在最小生成树上(最小生成树=最小瓶颈生成树) 于是我们建出kruskal重 ...

  9. [JZOJ 5912] [NOIP2018模拟10.18] VanUSee 解题报告 (KMP+博弈)

    题目链接: https://jzoj.net/senior/#contest/show/2530/2 题目: 众所周知,cqf童鞋对哲学有着深入的理解和认识,并常常将哲学思想应用在实际生活中,例如锻炼 ...

随机推荐

  1. c语言循环案例

    do while #include <stdio.h> #include <stdlib.h> int main() { int a = 1,b = 10; do { b -= ...

  2. iOS-UIApplication详解

    UIApplication简介 UIApplication对象是应用程序的象征. 每一个应用程序都有自己的UIApplication对象,而且是单例. 一个iOS程序启动后创建的第一个对象就是UIAp ...

  3. leetcode 系列文章目录

    leetcode 系列文章目录 0. 两数之和1. 两数相加 2. 无重复字符的最长子串 3. 寻找两个有序数组的中位数 4. 最长回文子串 5. Z 字形变换 6. 整数反转 7. 字符串转换整数 ...

  4. radio判断是否为空

    isMarital = $('[name="isMarital"]:checked').val(); isMarital == null //当radio选择为空的时候 isMar ...

  5. SwipeRefreshLayout的使用,下拉刷新

    1. <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android ...

  6. web.xml中的url-pattern写法规则及匹配过程

    servlet和filter在javaEE开发中很常用,因此有必要知道web.xml文件映射的规则 1.  写法 ①完全匹配:以“/”开头,以字母(非“*”)结束    如:<url-patte ...

  7. GRpc-Go使用笔记

      linux下配置GRpc-golang 1.git中下载protobuf包 2.解压(/usr/local/protobuf) unzip protobuf-cpp-3.0.0-alpha-3.z ...

  8. ZBrush破解版真的好用么?

    安装ZBrush®的时候是不是经常出现各种奇葩问题,使用ZBrush时候是不是经常出现停止工作状况,究其原因,原来都是破解搞的鬼.ZBrush破解版你还敢用么? 随着国人对版权的重视,越来越多的制作商 ...

  9. 密信(Mesince)首创全自动邮件加密,颠覆传统邮件加密软件

    电子邮件泄密已经成为一个全球性的日益严峻的安全问题,解决这个问题的唯一有效办法就是电子邮件内容先加密后发送.然而,使用基于S/MIME标准的传统邮件加密软件进行邮件加密,需要用户具备一定的技术基础.用 ...

  10. js获取路径参数对象

    /** * 获取页面路径参数值 */ function getParams(key) { var result = {}; var paramStr = encodeURI(window.docume ...