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. 如何嵌套一个网页html到另一个html中

    在常规网页开发中(单页应用除外哈),经常会遇到把一些通用内容的页面集中到一个页面中,需要使用这些页面只需要包含引入即可,这样有利于维护和修改,当通用页面修改时只需更改一个文件就可以了,不需要每个文件单 ...

  2. 二、web自动化快速使用

      1.启动浏览器 from selenium import webdriver # 启动谷歌浏览器,依赖:先安装好chromedriver.exe驱动 # 方式1.当chrome.driver放在p ...

  3. 「单调队列优化DP」P2034 选择数字

    「单调队列优化DP」P2034 选择数字 题面描述: 给定一行n个非负整数a[1]..a[n].现在你可以选择其中若干个数,但不能有超过k个连续的数字被选择.你的任务是使得选出的数字的和最大. 输入格 ...

  4. Virtual DOM 真的比操作原生 DOM 快吗?

    附上尤大的回答链接链接:https://www.zhihu.com/question/31809713/answer/53544875

  5. 数据可视化之powerBI入门(四)Power BI与PowerQuery、PowerPivot有什么关系

    https://zhuanlan.zhihu.com/p/64146209 Power BI与PowerQuery.PowerPivot有什么关系? 刚开始学习PowerBI的时候,总是能碰到Powe ...

  6. Python并发编程05 /死锁现象、递归锁、信号量、GIL锁、计算密集型/IO密集型效率验证、进程池/线程池

    Python并发编程05 /死锁现象.递归锁.信号量.GIL锁.计算密集型/IO密集型效率验证.进程池/线程池 目录 Python并发编程05 /死锁现象.递归锁.信号量.GIL锁.计算密集型/IO密 ...

  7. 关于Haskell计算斐波那契数列的思考

    背景 众所周知,Haskell语言是一门函数式编程语言.函数式编程语言的一大特点就是数值和对象都是不可变的,而这与经常需要对状态目前的值进行修改的动态规划算法似乎有些"格格不入", ...

  8. Python基础点记录1

    1 变量:一个变量就是一个单词,只有一个单一的值 1 Python里面的数据类型 interage , floats , booleans , String等 2 Python是一个区分大小写的语言 ...

  9. 题解 SP3734 【PERIODNI - Periodni】

    考虑用\(DP\)和组合数学来解决. 因为原图像不规则的形状不好处理,所以先用笛卡尔树(性质为小根堆)将其划分成一个一个的矩形. 发现在笛卡尔树上的每个节点都对应一个矩形,矩形高为\(h_x-h_{f ...

  10. git 缓存密码 unable to access... 403错误

    如果输入了 git config credential.helper 命令之后还是出现了osxkeychain, store 或者 cache 等,说明 git 的配置还是没有被清空,我参考了stac ...