[JZOJ 5909] [NOIP2018模拟10.16] 跑商(paoshang) 解题报告 (圆方树)
题目链接:
https://jzoj.net/senior/#contest/show/2529/2
题目:
题目背景:
尊者神高达很穷,所以他需要跑商来赚钱
题目描述:
基三的地图可以看做 n 个城市,m 条边的无向图,尊者神高达会从任意一个点出发并在起点购买货物,在旅途中任意一点卖出并最终到达终点,尊者神高达的时间很宝贵,所以他不会重复经过同一个城市,但是为了挣钱,他可能会去绕路。当然,由于工作室泛滥,所以一个城市的货物价格可能会发生改变。但是尊者神高达智商不足,他可能在一个很蠢的节点把货物卖掉,所以尊者神高达想知道每一次跑商最多能赔多少钱。
题目大意:
一张无向图,询问两点之间的可能的路径上的最小点权,带修改
前置知识点:
圆方树相关内容
首先我们看圆方树
圆方树连边规则:
如果一条边在仙人掌中不属于任何一个环中,那么它直接圆方树中的两个圆点。
对于仙人掌中的任意一个环,则每个环上的点在圆方树上对应的圆点向这个环对应的方点连边。如下图所示
注意圆方树只适用于仙人掌
怎么构造圆方树呢?
代码实现大概是这样的
void tarjan(int x,int pre) {dfn[x]=low[x]=++js;sta[++tp]=x;for (int i=h1[x];i;i=e1[i].nxt){if (i==(pre^1)) continue;int y=e1[i].to;if (!dfn[y]){tarjan(y,i);low[x]=min(low[x],low[y]);if (low[y]>dfn[x]) link2(x,y),tp--;//找到桥 if (low[y]==dfn[x])//x在边双里 {for (++nn,link2(x,nn);sta[tp]!=x;tp--) A[nn].insert(a[sta[tp]]),link2(nn,sta[tp]);}}else low[x]=min(low[x],dfn[y]);} }
那么广义圆方树呢?
构造方法和圆方树区别不大,就是强制把两点一线也看成一个点双,建方点即可。
广义圆方树可以适用于无向图,而不只是仙人掌
题解:
言归正传,这道题我们怎么做?
如果没有修改的话,很显然,每个方点的值为这个点双中权值最小的点。 这样,就变成了裸的求树上两点路径上最小值,剖一下就行了
考虑这样怎么修改,记录下每一个圆点连接的方点,开个set维护一下每个方点连接的原点。对于修改的原点一个个修改每个与它相连的方点,但如果这个点是一个割点(连接很多个方点),那么可能就需要修改很多次,时间复杂度就不对了
题解用了更优秀的做法
把圆方树变成一个有根树,方点的值改为记录环上除环的根外权值最小的点,这样每个圆点只有一个对应的方点。如果 LCA 是方点,只需特判一下LCA的父亲。画个图理解吧
然而代码里写的广义圆方树用的是圆方树的构造方法,身为蒟蒻的我不知道两种构造方法有什么区别...这是我第一次写圆方树
还有与圆方树类似的做法,就是对每一个边双维护一个set,每次修改就是修改这个点所在的边双即可
注意边双和点双都意味着其中的任意两个点可以经过任意一个想经过的点到达彼此
#include<iostream> #include<cstring> #include<cstdio> #include<algorithm> #include<set> using namespace std;const int N=2e5+15; const int inf=1e9; int n,m,tot1=1,tot2=1,js,tp,nn; int a[N],h1[N],h2[N],dfn[N],low[N],sta[N],siz[N],dd[N],id[N],dep[N],son[N],top[N],pf[N]; int mi[N<<2]; multiset <int> A[N]; struct EDGE {int to,nxt; }e1[N<<1],e2[N<<1]; inline int read() {char ch=getchar();int s=0,f=1;while (ch<'0'||ch>'9') {if (ch=='-') f=-1;ch=getchar();}while (ch>='0'&&ch<='9') {s=(s<<3)+(s<<1)+ch-'0';ch=getchar();}return s*f; } void link1(int u,int v) { e1[++tot1]=(EDGE){v,h1[u]};h1[u]=tot1; } void link2(int u,int v) { pf[v]=u;e2[++tot2]=(EDGE){v,h2[u]};h2[u]=tot2; } void tarjan(int x,int pre)//构造园方树 {dfn[x]=low[x]=++js;sta[++tp]=x;for (int i=h1[x];i;i=e1[i].nxt){if (i==(pre^1)) continue;int y=e1[i].to;if (!dfn[y]){tarjan(y,i);low[x]=min(low[x],low[y]);if (low[y]>dfn[x]) link2(x,y),tp--;//找到桥 if (low[y]==dfn[x])//x在点双里 {for (++nn,link2(x,nn);sta[tp]!=x;tp--) A[nn].insert(a[sta[tp]]),link2(nn,sta[tp]);}}else low[x]=min(low[x],dfn[y]);} } void dfs1(int x) {siz[x]=1;for (int i=h2[x];i;i=e2[i].nxt){int y=e2[i].to;if (y==pf[x]) continue;dep[y]=dep[x]+1;dfs1(y);siz[x]+=siz[y];if (!son[x]||siz[y]>siz[son[x]]) son[x]=y;} } void dfs2(int x,int tt) {dd[x]=++js;id[js]=x;top[x]=tt;if (!son[x]) return;dfs2(son[x],tt);for (int i=h2[x];i;i=e2[i].nxt){int y=e2[i].to;if (y==pf[x]||y==son[x]) continue;dfs2(y,y);} } #define mid ((l+r)>>1) void pushup(int o) {mi[o]=min(mi[o<<1],mi[o<<1|1]);} void build(int o,int l,int r) {if (l==r) {mi[o]=a[id[l]];return;}build(o<<1,l,mid);build(o<<1|1,mid+1,r);pushup(o); } void update(int o,int l,int r,int x,int y) {if (l==r) {mi[o]=y;return;}if (x<=mid) update(o<<1,l,mid,x,y);else update(o<<1|1,mid+1,r,x,y);pushup(o); } int query(int o,int l,int r,int x,int y) {if (l>=x&&r<=y) return mi[o];int re=inf;if (x<=mid) re=min(re,query(o<<1,l,mid,x,y));if (y>mid) re=min(re,query(o<<1|1,mid+1,r,x,y));return re; } int query_min(int x,int y) {int re=inf;while (top[x]!=top[y]){if (dep[top[x]]<dep[top[y]]) swap(x,y);re=min(re,query(1,1,nn,dd[top[x]],dd[x]));x=pf[top[x]];}if (dep[x]<dep[y]) swap(x,y);re=min(re,query(1,1,nn,dd[y],dd[x]));if (y>n&&pf[y]) re=min(re,a[pf[y]]);//特判LCA是否是方点,如果是的话还需要考虑它的父亲 return re; } int main() {freopen("paoshang.in","r",stdin);freopen("paoshang.out","w",stdout);n=read();m=read();nn=n;for (int i=1;i<=n;i++) a[i]=read();for (int i=1,u,v;i<=m;i++){u=read();v=read();link1(u,v);link1(v,u);} js=0;tarjan(1,-1);for (int i=n+1;i<=nn;i++) a[i]=*A[i].begin();dep[1]=1;dfs1(1);js=0;dfs2(1,1);build(1,1,nn);int q=read(),pr,pl;char op[5];while (q--){scanf("%s",op);if (op[0]=='C'){int x=read(),y=read();update(1,1,nn,dd[x],y);if ((pr=pf[x])>n){A[pr].erase(A[pr].find(a[x]));A[pr].insert(y);if (a[pr]!=(pl=*A[pr].begin())) update(1,1,nn,dd[pr],pl),a[pr]=pl;}a[x]=y;}if (op[0]=='Q'){int x=read(),y=read();printf("%d\n",a[x]-query_min(x,y));}}return 0; }
转载于:https://www.cnblogs.com/xxzh/p/9800499.html
[JZOJ 5909] [NOIP2018模拟10.16] 跑商(paoshang) 解题报告 (圆方树)相关推荐
- JZOJ 5909. 【NOIP2018模拟10.16】跑商(paoshang)
Description 题目背景: 尊者神高达很穷,所以他需要跑商来赚钱 题目描述: 基三的地图可以看做 n 个城市,m 条边的无向图,尊者神高达会从任意一个点出发并在起点购买货物,在旅途中任意一点卖 ...
- 5909. 【NOIP2018模拟10.16】跑商(圆方树+树链剖分+SET)
题目大意: 基三的地图可以看做 n 个城市,m 条边的无向图,尊者神高达会从任意一个点出发并在起点购买货物,在旅途中任意一点卖出并最终到达终点,尊者神高达的时间很宝贵,所以他不会重复经过同一个城市,但 ...
- jzoj5909 【NOIP2018模拟10.16】跑商(圆方树性质+树剖)
Description 一个无向图,求从i到j简单路径(无重点)上的最小点权. n,m<=1e5 分析 考虑走到某个点双上时,假如不是同点进同点出,就可以获得这个点双上的所有贡献. 于是建出圆方 ...
- [JZOJ5909]【NOIP2018模拟10.16】跑商【圆方树】【树链剖分】
Description 基三的地图可以看做 n 个城市,m 条边的无向图,尊者神高达会从某个点出发并在起点购买货物,在旅途中任意一点卖出并最终到达终点,尊者神高达的时间很宝贵,所以他不会重复经过同一个 ...
- JZOJ 5907. 【NOIP2018模拟10.16】轻功(qinggong)
Description 题目背景: 尊者神高达进入了基三的世界,作为一个 mmorpg 做任务是必不可少的,然而跑地图却令人十分不爽.好在基三可以使用轻功,但是尊者神高达有些手残,他决定用梅花桩练习轻 ...
- [JZOJ 5911] [NOIP2018模拟10.18] Travel 解题报告 (期望+树形DP)
题目链接: http://172.16.0.132/senior/#contest/show/2530/1 题目: EZ同学家里非常富有,但又极其的谦虚,说话又好听,是个不可多得的人才. ...
- [jzoj 6093] [GDOI2019模拟2019.3.30] 星辰大海 解题报告 (半平面交)
题目链接: https://jzoj.net/senior/#contest/show/2686/2 题目: 题解: 说实话这题调试差不多花了我十小时,不过总算借着这道题大概了解了计算几何的基础知识 ...
- jzoj 5906. 【NOIP2018模拟10.15】传送门(树形dp)
5906. [NOIP2018模拟10.15]传送门 Description 8102年,Normalgod在GLaDOS的帮助下,研制出了传送枪.但GLaDOS想把传送枪据为己有,于是把Normal ...
- [圆方树][树链剖分][set]JZOJ 5909 跑商
Description 题目背景: 尊者神高达很穷,所以他需要跑商来赚钱 题目描述: 基三的地图可以看做 n 个城市,m 条边的无向图,尊者神高达会从任意一个点出发并在起点购买货物,在旅途中任意一点卖 ...
最新文章
- 《QTP自动化测试进阶》(1)
- Python实现与LeetCode--堆
- SQL2008 附加数据库提示 5120错误
- 答应我,调试Python代码,不要再用Print了!
- gb50268-2008给水排水管道施工及验收规范_20135城市非开挖管道施工质量检查与验收(夯管·定向钻·顶管)...
- matlab产生正态分布样本
- Android HTTP POST上传
- 带有Angular JS的Java EE 7 –第1部分
- 快速安装配置zabbix_agent端
- 对于electron-react-boilerplate(ERB)的学习笔记(legacy)
- python写登录界面跳转至数据库操作_pycharm+jdango+python实现创建web工程并实现简单登陆...
- 从 Netflix 到 Alibaba,Spring Cloud 更好了吗?
- TTL转USB 六合一
- 致远OA_0day批量植Cknife马一步到位
- PDF格式分析(六)PDF版本
- 2020年中国旅游行业网络关注度分析报告
- [转]大连金州不相信眼泪
- 思科2960交换机光口激活失败,提示has bad crc,解决方法
- Qt QWidget播放视频背景图片闪烁
- 2021-2027全球与中国成像色度计市场现状及未来发展趋势