LINK:探险队



非常难的题目 考试的时候爆零了 完全没有想到到到底怎么做 (当时去刚一道数论题了。

首先考虑清楚一件事情 就是当前是知道整张地图的样子 但是不清楚到底哪条边断了。

所以我们要做的其实就是选择最优的路线 使得遇到断边情况下是最优的。

可以发现在某个点出现断边的时候 此时断的一定是这个点到终点最短路上的边 这样是最差的结果。

那么其实就是断边只会断由T发出的最短路树上的边。

到达某个点知道断边之后 其实要求出断开这条边再到T的最短路。

暴力是\(nm\cdot logn\)的 考虑更快的求法 当前点可以通过非最短路边到达另外一个点 或者是自己子树内的一条边到达另外的点再沿着另外的点的最短路走。

维护子树内这样边的最小值可以线段树 最快的做法是 可并堆。记\(h_x\)表示x处断了最短路的边到T的最小值。

复杂度\(n\cdot logn\).

接下来考虑怎么求答案.

一个比较\(naiv\)e的想法是 不是求最优线路么?可以把所有最优的线路给搜出来。

对于初始选择这条线路的最大代价为\(\max{h_x+dis_x}\)所有之中选\(min\)即可。

这启示我们求S到T的所有路径的代价为上述的那个东西 从S开始dp没有什么用 因为当前的选择 需要知道以后的决策。

如 当前如果选择断边 是要知道以后断边的结果会更好 当前选择不断边 要知道以后断边的结果会更差.

所以需要倒序dp.

设\(f_x\)表示从x到T的最短路/设\(f_{x,0/1}\)表示从x到T的最短路此时是否断边了.

那么其实我们知道以后的状态就可以决断现在的状态了.

\(f_{x,0}=f_{tn,0}+e[i],f_{x,1}=max(min(f_{tn,1}+e[i]),h_x)\)

最后的答案即为\(f_{S,1}\) 由此可以发现好像第一个状态不是很必要。

为了让状态具有最优性可以利用dij进行转移。

感觉很难 希望以后遇到这种问题可以会做吧!

code
//#include<bits\stdc++.h>
#include<iostream>
#include<iomanip>
#include<cstdio>
#include<cstring>
#include<string>
#include<ctime>
#include<cmath>
#include<cctype>
#include<cstdlib>
#include<queue>
#include<deque>
#include<stack>
#include<vector>
#include<algorithm>
#include<utility>
#include<bitset>
#include<set>
#include<map>
#define ll long long
#define db double
#define INF 1000000000000000000ll
#define ldb long double
#define pb push_back
#define put_(x) printf("%d ",x);
#define get(x) x=read()
#define gt(x) scanf("%d",&x)
#define gi(x) scanf("%lf",&x)
#define put(x) printf("%d\n",x)
#define putl(x) printf("%lld\n",x)
#define gc(a) scanf("%s",a+1)
#define rep(p,n,i) for(RE int i=p;i<=n;++i)
#define go(x) for(int i=lin[x],tn=ver[i];i;tn=ver[i=nex[i]])
#define fep(n,p,i) for(RE int i=n;i>=p;--i)
#define vep(p,n,i) for(RE int i=p;i<n;++i)
#define pii pair<ll,int>
#define mk make_pair
#define RE register
#define P 1000000007
#define gf(x) scanf("%lf",&x)
#define pf(x) ((x)*(x))
#define uint unsigned long long
#define ui unsigned
#define EPS 1e-4
#define sq sqrt
#define S second
#define F first
#define V vector
using namespace std;
char buf[1<<15],*fs,*ft;
inline char getc()
{
return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?0:*fs++;
}
inline int read()
{
RE int x=0,f=1;RE char ch=getc();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getc();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getc();}
return x*f;
}
const int MAXN=200010,maxn=500010<<1;
int n,m,ss,tt,cnt,len=1;
ll dis[MAXN],h[MAXN],c[MAXN];
int vis[MAXN],v[MAXN],f[MAXN][20],Log[MAXN],d[MAXN];V<int>g[MAXN],s[MAXN];
int lin[MAXN],pos[maxn],nex[maxn],ver[maxn],e[maxn];
int root[MAXN],lc[maxn],rc[maxn],b[maxn];
pii w[maxn];
inline void add(int x,int y,int z)
{
ver[++len]=y;
nex[len]=lin[x];
lin[x]=len;
e[len]=z;
}
priority_queue<pii> q;
inline void dij()
{
q.push(mk(0,tt));
rep(1,n,i)dis[i]=INF;dis[tt]=0;
while(q.size())
{
int x=q.top().S;q.pop();
if(vis[x])continue;
vis[x]=1;
go(x)
{
if(dis[tn]>dis[x]+e[i])
{
dis[tn]=dis[x]+e[i];
f[tn][0]=x;v[tn]=i;
q.push(mk(-dis[tn],tn));
}
}
}
}
inline void dfs(int x)
{
d[x]=d[f[x][0]]+1;
rep(1,Log[d[x]],i)f[x][i]=f[f[x][i-1]][i-1];
vep(0,g[x].size(),j)dfs(g[x][j]);
}
inline int LCA(int x,int y)
{
if(d[x]<d[y])swap(x,y);
fep(Log[d[x]],0,i)if(d[f[x][i]]>=d[y])x=f[x][i];
if(x==y)return x;
fep(Log[d[x]],0,i)if(f[x][i]!=f[y][i])x=f[x][i],y=f[y][i];
return f[x][0];
}
inline int merge(int x,int y)//左偏树的性质 左边比右边满.
{
if(!x||!y)return x|y;
if(w[x]>w[y])swap(x,y);
rc[x]=merge(rc[x],y);
if(b[lc[x]]<b[rc[x]])swap(lc[x],rc[x]);
b[x]=b[rc[x]]+1;
return x;
}
inline void dp(int x)
{
vep(0,g[x].size(),i)dp(g[x][i]),root[x]=merge(root[x],root[g[x][i]]);
vep(0,s[x].size(),i)root[x]=merge(root[x],s[x][i]);
while(root[x])
{
if(d[w[root[x]].S]>=d[x])
{
root[x]=merge(lc[root[x]],rc[root[x]]);
continue;
}
else
{
h[x]=w[root[x]].F-dis[x];
break;
}
}
}
int main()
{
//freopen("1.in","r",stdin);
freopen("expedition.in","r",stdin);
freopen("expedition.out","w",stdout);
get(n);get(m);get(ss);get(tt);
if(ss==tt){puts("0");return 0;}
rep(1,m,i)
{
int get(x),get(y),get(z);
add(x,y,z);add(y,x,z);
}
dij();Log[0]=-1;
rep(1,n,i)
{
if(f[i][0])g[f[i][0]].pb(i);
Log[i]=Log[i>>1]+1;
pos[v[i]>>1]=1;h[i]=INF;c[i]=INF;vis[i]=0;
}
dfs(tt);
rep(1,m,i)
{
if(pos[i])continue;
w[++cnt]=mk(dis[ver[i<<1]]+dis[ver[i<<1|1]]+e[i<<1],LCA(ver[i<<1],ver[i<<1|1]));
s[ver[i<<1]].pb(cnt);++cnt;w[cnt]=w[cnt-1];s[ver[i<<1|1]].pb(cnt);
}
dp(tt);
q.push(mk(0,tt));c[tt]=0;h[tt]=0;
while(q.size())
{
int x=q.top().S;q.pop();
if(vis[x])continue;
vis[x]=1;
go(x)
{
if(c[tn]>max(c[x],h[x])+e[i])
{
c[tn]=max(c[x],h[x])+e[i];
q.push(mk(-max(c[tn],h[tn]),tn));
}
}
}
if(max(h[ss],c[ss])>=INF)puts("-1");
else putl(max(h[ss],c[ss]));
return 0;
}

7.12 NOI模拟赛 探险队 期望 博弈 dp 最坏情况下最优策略 可并堆的更多相关文章

  1. 7.12 NOI模拟赛 生成树 装压dp vector装压

    LINK:生成树 这场比赛我打的真失败 T3是比较容易的 却一直刚 那道"数论" 10分其实搜一下全排列. 30分容易想到对边进行装压dp. 不过存在一些细节 可以对于一个连通块的 ...

  2. 7.12 NOI模拟赛 积性函数求和 数论基础变换 莫比乌斯反演

    神题! 一眼powerful number 复习了一下+推半天. 可以发现G函数只能为\(\sum_{d}[d|x]d\) 不断的推 可以发现最后需要求很多块G函数的前缀和 发现只有\(\sqrt(n ...

  3. 7.9 NOI模拟赛 C.走路 背包 dp 特异性

    (啊啊啊 什么考试的时候突然降智这题目硬生生没想出来. 容易发现是先走到某个地方 然后再走回来的 然后在倒着走的路径上选择一些点使得最后的得到的最多. 设\(f_{i,j}\)表示到达i这个点选择的价 ...

  4. NOI模拟赛 Day1

    [考完试不想说话系列] 他们都会做呢QAQ 我毛线也不会呢QAQ 悲伤ING 考试问题: 1.感觉不是很清醒,有点困╯﹏╰ 2.为啥总不按照计划来!!! 3.脑洞在哪里 4.把模拟赛当作真正的比赛,紧 ...

  5. 6.28 NOI模拟赛 好题 状压dp 随机化

    算是一道比较新颖的题目 尽管好像是两年前的省选模拟赛题目.. 对于20%的分数 可以进行爆搜,对于另外20%的数据 因为k很小所以考虑上状压dp. 观察最后答案是一个连通块 从而可以发现这个连通块必然 ...

  6. 【2019.3.20】NOI模拟赛

    题目 这里必须标记一下那个傻逼问题,再不解决我人就没了! 先放一个 $T3$ $20$ 分暴力 #include<bits/stdc++.h> #define rep(i,x,y) for ...

  7. 7.1 NOI模拟赛 凸包套凸包 floyd 计算几何

    计算几何之所以难学 就是因为太抽象了 不够直观 而且情况很多 很繁琐 甚至有一些东西不清不楚.. 这道题注意到题目中的描述 一个鸽子在两个点所连直线上也算. 通过看题解 发现这个地方并非直线而是线段 ...

  8. 10年省赛-Greatest Number (二分+暴力) + 12年省赛-Pick apples(DP) + UVA 12325(暴力-2次枚举)

    题意:给你n个数,在里面取4个数,可以重复取数,使和不超过M,求能得到的最大的数是多少: 思路:比赛时,和之前的一个题目很像,一直以为是体积为4(最多选择四次)的完全背包,结果并不是,两两求和,然后二 ...

  9. 【2018.12.10】NOI模拟赛3

    题目 WZJ题解 大概就是全场就我写不过 $FFT$ 系列吧……自闭 T1 奶一口,下次再写不出这种 $NTT$ 裸题题目我就艹了自己 -_-||| 而且这跟我口胡的自创模拟题 $set1$ 的 $T ...

随机推荐

  1. 附007.Docker全系列大总结

    Docker全系列总结如下,后期不定期更新. 欢迎基于学习.交流目的的转载和分享,禁止任何商业盗用,同时希望能带上原文出处,尊重ITer的成果,也是尊重知识. 若发现任何错误或纰漏,留言反馈或右侧添加 ...

  2. git bash中提示 bash:node: command not found

    昨天小伙伴私信,git bash以及windows 的cmd命令行下均无法运行node npm. 究其原因是环境变量的问题.解决步骤: 1>在"此电脑"中右击,选择" ...

  3. css3 自定义字体_使用@font-face方式实现个性化字体

    当我们在浏览一些网站时发现,里面含有一些十分个性的字体,这些字体并不是我们电脑上安装的字体.那么css是如何实现自定义字体的呢? 资源网站大全https://55wd.com 在css3中可以通过@f ...

  4. Maven一键部署Springboot到Docker仓库,为自动化做准备

    1 前言 前面<Springboot整合MongoDB的Docker开发,其它应用也类似>讲解了如何做Docker开发.如何把Springboot应用打包成一个镜像,但它是手动的,本文将讲 ...

  5. 使用CodeMirror插件遇到的问题

    CodeMirror的正常使用: //首先通过<script>标签引入相应的js,这个就不必说了 var myCodeMirror = CodeMirror.fromTextArea(my ...

  6. 大型Java进阶专题(七) 设计模式之委派模式与策略模式

    前言 ​ 今天开始我们专题的第七课了.本章节将介绍:你写的代码中是否觉得很臃肿,程序中有大量的if...else,想优化代码,精简程序逻辑,提升代码的可读性,这章节将介绍如何通过委派模式.策略模式让你 ...

  7. flask 源码专题(二):请求上下文与全文上下文

    源码解析 0. 请求入口 if __name__ == '__main__': app.run() def run(self, host=None, port=None, debug=None, lo ...

  8. bzoj2296【POJ Challenge】随机种子*

    bzoj2296[POJ Challenge]随机种子 题意: 求一个≤10^16的数,使这个数包含123456789且为x的倍数.x≤1000000. 题解: 16-6刚好等于10.因此我们可以直接 ...

  9. 【一起学系列】之命令模式:封装一个简单Jedis

    意图 将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化:对请求排队或记录请求日志,以及支持可撤销的操作. 命令模式的诞生 [产品]:开发小哥,来活啦,咱们需要设计一款遥控器,核心功能就 ...

  10. Python实现性能自动化测试竟然如此简单【颠覆你的三观】

    一.思考 1.什么是性能自动化测试?   性能系统负载能力 超负荷运行下的稳定性 系统瓶颈 自动化测试使用程序代替手工 提升测试效率 性能自动化使用代码模拟大批量用户 让用户并发请求 多页面多用户并发 ...