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. [Python] datetime.timedelta模块用法

    python使用datetime模块timedelta实现日期时间相加: python计算明天的日期: from datetime import datetime from datetime impo ...

  2. Meta标签大全_web开发常用meta整理

    meta标签提供关于HTML文档的元数据.元数据不会显示在页面上,但是对于机器是可读的.它可用于浏览器(如何显示内容或重新加载页面),搜索引擎(关键词),或其他 web 服务. 必要属性 属性 值 描 ...

  3. 3dTiles 数据规范详解[3] 内嵌在瓦片文件中的两大数据表

    转载请声明出处:全网@秋意正寒 零.本篇前言 说实话,我很纠结是先介绍瓦片的二进制数据文件结构,还是先介绍这两个重要的表.思前想后,我决定还是先介绍这两个数据表. 因为这两个表不先给读者灌输,那么介绍 ...

  4. sass安装与教程

    首先下载ruby http://dlsw.baidu.com/sw-search-sp/soft/ff/22711/rubyinstaller_V2.2.2.95_setup.1439890355.e ...

  5. MySQL 事务 异常 事务隔离的级别

    MySQL 事务 异常 事务隔离的级别   事务 在你操作数据库的同时,有可能其他用户还会不断地对数据进行增删改查操作.为了避免并行进行时出现混乱,就产生了"事务".事务就是要保证 ...

  6. [JAVA]解决不同浏览器下载附件的中文名乱码问题

    附件下载时,遇到中文附件名的兼容性问题,firefox.chrome.ie三个派系不兼容,通过分析整理,总结出处理该问题的办法,记录如下: 1.文件名编码 服务器默认使用的是ISO8859-1,而我们 ...

  7. JVM 专题十四:本地方法接口

    1. 本地方法接口 2. 什么是本地方法? 简单来讲,一个Native Method就是一个Java调用非Java代码的接口.一个Native Method是这样一个java方法:该方法的实现由非Ja ...

  8. java 面向对象(五):类结构 方法(二) 关键字:return;方法的重载;可变个数形参的方法

    return关键字:1.使用范围:使用在方法体中2.作用:① 结束方法 * ② 针对于返回值类型的方法,使用"return 数据"方法返回所要的数据.3.注意点:return关键字 ...

  9. 机器学习实战基础(二十一):sklearn中的降维算法PCA和SVD(二) PCA与SVD 之 降维究竟是怎样实现

    简述 在降维过程中,我们会减少特征的数量,这意味着删除数据,数据量变少则表示模型可以获取的信息会变少,模型的表现可能会因此受影响.同时,在高维数据中,必然有一些特征是不带有有效的信息的(比如噪音),或 ...

  10. OSCP Learning Notes - Enumeration(3)

    SMB Enumeration 1. Set the smb configurations. locate smb.conf vim /etc/samba/smb.conf Insert the gl ...