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. 如何写出高性能的CSS3动画

    小伙伴们在写CSS3动画时,会发现在手机上很多时候会感到卡顿,然后Google到的解决方案大多是开启GPU加速transform: translate3d(0,0,0); 可解决,但是为什么开启GPU ...

  2. 多线程01-CAS (CompareAndSwap)

    1.基本概念 原子性是不可中断的最小操作:在Java中,一般通过加锁或者自旋CAS方式来确保原子操作: 而CAS(compareAnd swap)作为Java中常用的保证原子性的手段,JDK1.5之后 ...

  3. Docker 安装并使用mysql

    上一篇介绍了Docker在CentOS中的安装,本文介绍如何在Docker中安装并使用mysql 1.拉取最新的mysql镜像 [root]# docker pull mysql 2.查看已有镜像 [ ...

  4. P2295 MICE 网格中的DP

    题目描述 分析 很好的一道网格中的\(DP\)题 我们设\(f[x][y]\)为小象到达坐标为\((x,y)\)的点时看到的最少的老鼠的数量 但是这样定义是不好转移的,因为小象可能从上面的格子转移下来 ...

  5. 管理用户和组 、 tar备份与恢复 、 cron计划任务-云计算学习(4)

    配置用户和组账号 问题 本例要求创建下列用户.组以及组的成员关系: 新建用户 alex,其用户ID为3456,密码是flectrag 创建一个名为 adminuser 的组 创建一个名为 natash ...

  6. 利用docker部署elk交换机日志分析

    今天我们来聊一下利用docker部署elk日志分析系统,这里解析一下elk是啥东西.elk分别是Elasticsearch,Logstash和Kibana的首字母缩写. Elasticsearch是一 ...

  7. JavaScript的参数是按照什么方式传递的?

    1.基本类型传递方式 <script> var a = 1; function test(x) { x = 10; console.log(x); } test(a); // consol ...

  8. 机器学习实战基础(十五):sklearn中的数据预处理和特征工程(八)特征选择 之 Filter过滤法(二) 相关性过滤

    相关性过滤 方差挑选完毕之后,我们就要考虑下一个问题:相关性了. 我们希望选出与标签相关且有意义的特征,因为这样的特征能够为我们提供大量信息.如果特征与标签无关,那只会白白浪费我们的计算内存,可能还会 ...

  9. Flask 基础组件(五):请求和响应

    from flask import Flask from flask import request from flask import render_template from flask impor ...

  10. 收集TCP端口的访问延迟和丢包率

    需求: 找一款工具可以对TCP 80端口 收集 访问延迟和丢包率 找到的工具: 1.Hping :  http://www.hping.org/ 2.paping : https://docs.azu ...