题目链接:

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. htmlunit 简单操作

    首先我们新建一个Maven普通客户端项目,然后打开pom.xml 引入htmlunit支持: <dependency> <groupId>net.sourceforge.htm ...

  2. Spring《三》ref 引用其他bean

    local属性 1.被引用id必须在同一个xml中. 2.被引用id必须使用id命名. 优点提前检查所使用的bean id是否正确. Bean属性 1.Bean指定的id可以在不同的xml中. 2.B ...

  3. Spark SQL 编程API入门系列之SparkSQL的依赖

    不多说,直接上干货! 不带Hive支持 <dependency> <groupId>org.apache.spark</groupId> <artifactI ...

  4. Java标识符规范

    1.标识符用来定义包名,类名,方法名,变量名,常量名. 2.标识符必须由字母.下划线.$符号组成,不能以数字开头.不能是Java中的保留关键字.

  5. CREC 2017

    A:Assignment Algorithm #include <bits/stdc++.h> using namespace std; ][]; ][],n,m,ans=,A,B,l=, ...

  6. 用IIS怎样在局域网内建网站

    IIS服务器组建一览 IIS(Internet Information Server,互联网信息服务)是一种Web(网页)服务组件,其中包括Web服务器.FTP服务器.NNTP服务器和SMTP服务器, ...

  7. jsp错误页面的处理

    局部的错误处理 1,errorpage 在错误页面指令page中声明errorpage="要显示的页面地址" 在要显示的页面page中声明iserrorpage="tru ...

  8. video标签实现简单视频背景+遇到问题(视频无法显示,不能自动播放)

    最近看网上有一些网站首页背景是炫酷的视频背景,就想模拟一个 1.video标签简介 video标签定义视频,就是可以在网页上实现视频的播放,详情见http://www.w3school.com.cn/ ...

  9. [BZOJ1322]Destroying The Graph

    题目大意:有一张有向图,对于每个点,有两种操作:1. 删掉它的所有入边2. 删掉它的所有出边对每个点的每个操作均有不同的价值.求使得图上没有边的最小价值.解题思路:考虑把点拆成入点和出点,然后就是二分 ...

  10. debian 9 安装无线网卡

    #添加源 echo "deb http://httpredir.debian.org/debian/ stretch main contrib non-free" >> ...