[loj2842]野猪
首先,并不一定走“除了上一次来的边”以外的最短路,但考虑“除了上一次来的边”以外的最短路和次短路(这里的次短路指最后一条边与最短路不同的“最短路”),必然是走这两者之一
(”除了上一次来的边“指第一步不走上一次来的边)
证明很显然,因为如果最短路不好必然是因为下一次需要先走最短路那条边,那么这次走次短路即可
但由于我们所预处理的并不能与实际的$X_{i}$有关(会有修改),但可以发现对于很多“上一次来的边”,其最短路和次短路都是一样的
具体来说,对于两点,求出:
1.最短路(任意一条,以下省略)
2.与最短路最后一条边不同的“最短路”
3.与最短路最后一条边不同且与第2条路径第一条边不同的“最短路”
4.与最短路第一条边的不同的“最短路”
5.与最短路第一条边不同且与第4条路径最后一条边不同的“最短路”
(前两个是用来查询除去的边没有用的情况,然后除去的边与次短路相同时修改次短路为第3条,除去的边与最短路相同时采用第4和第5条)
最短路的记录用第一条边、最后一条边的编号以及长度来描述最短路即可
事实上,这些都可以用$f_{i,j}$表示由第一次经过第$i$条边、最后一次经过第$j$条边(无向边拆为两条有向边来做)的最短路长度来处理,即枚举两点以及两边(总共$o(m^{2})$)
(有一个细节,就是要特殊处理存在直接路径的点对)
关于如何求$f_{i,j}$只需要把边当作点去求dijkstra即可,具体来说就是将原来的标记点改为标记边即可,但这样每一个边都做一次最坏会变为$o(m^{2})$,考虑到最短边仅仅只是自己的反向边没有更新,只需要用第二次搜到的边更新最短边的反向边即可
接下来用$dp_{i,j}$表示走到$X_{i}$且上一次选择的是第$j$种路径,根据上述信息不难转移
修改用线段树来维护这个dp,即对每一个区间维护一个5*5的矩阵表示$X_{l}$到$X_{l+1}$和$X_{r-1}$到$X_{r}$分别使用了什么路径,合并枚举$X_{mid}$到$X_{mid+1}$的路径即可
时间复杂度为$o(m^{2}\log_{2}m+5^{3}T\log_{2}L)$,可以通过
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
1 #include<bits/stdc++.h>
2 using namespace std;
3 #define N 2005
4 #define M 4005
5 #define ll long long
6 #define oo (1LL<<60)
7 #define T 100005
8 #define L (k<<1)
9 #define R (L+1)
10 #define mid (l+r>>1)
11 struct ji{
12 int nex,to,len;
13 }edge[M];
14 struct path{
15 int x,y;
16 ll d;
17 bool operator < (const path &k)const{
18 return d<k.d;
19 }
20 }f[5][N][N];
21 struct mat{
22 int l,r,len;
23 ll a[5][5];
24 path fl[5],fr[5];
25 }o,tr[T<<2];
26 priority_queue<pair<ll,int> >q;
27 int E,n,m,t,l,x,y,z,head[N],vis[M],visV[N];
28 ll ans,d[M],dis[M][M];
29 void add(int x,int y,int z){
30 edge[E].nex=head[x];
31 edge[E].to=y;
32 edge[E].len=z;
33 head[x]=E++;
34 }
35 void dij(int k){
36 memset(d,0x3f,sizeof(d));
37 memset(vis,0,sizeof(vis));
38 memset(visV,-1,sizeof(visV));
39 d[k]=edge[k].len;
40 q.push(make_pair(-d[k],k));
41 while (!q.empty()){
42 k=q.top().second;
43 q.pop();
44 if (vis[k])continue;
45 vis[k]=1;
46 x=edge[k].to;
47 if (visV[x]<0){
48 visV[x]=(k^1);
49 for(int i=head[x];i!=-1;i=edge[i].nex)
50 if (((k^i)!=1)&&(d[i]>d[k]+edge[i].len)){
51 d[i]=d[k]+edge[i].len;
52 q.push(make_pair(-d[i],i));
53 }
54 }
55 else{
56 y=visV[x];
57 if (d[y]>d[k]+edge[y].len){
58 d[y]=d[k]+edge[y].len;
59 q.push(make_pair(-d[y],y));
60 }
61 }
62 }
63 }
64 mat merge(mat x,mat y){
65 if (!x.len)return y;
66 if (!y.len)return x;
67 o.l=x.l,o.r=y.r,o.len=x.len+y.len;
68 memcpy(o.fl,x.fl,sizeof(o.fl));
69 memcpy(o.fr,y.fr,sizeof(o.fr));
70 memset(o.a,0x3f,sizeof(o.a));
71 if (x.len==1){
72 for(int i=0;i<5;i++){
73 o.fl[i]=f[i][x.l][y.l];
74 o.a[i][i]=f[i][x.r][y.l].d;
75 }
76 }
77 else{
78 for(int i=0;i<5;i++)
79 for(int j=0;j<5;j++)
80 for(int k=0;k<5;k++)
81 if ((x.fr[j].y^f[k][x.r][y.l].x)!=1)
82 o.a[i][k]=min(o.a[i][k],x.a[i][j]+f[k][x.r][y.l].d);
83 }
84 memcpy(x.a,o.a,sizeof(o.a));
85 memset(o.a,0x3f,sizeof(o.a));
86 if (y.len==1){
87 for(int i=0;i<5;i++){
88 o.fr[i]=f[i][x.r][y.r];
89 o.a[i][i]=0;
90 }
91 }
92 else{
93 for(int i=0;i<5;i++)
94 for(int j=0;j<5;j++)
95 for(int k=0;k<5;k++)
96 if ((f[i][x.r][y.l].y^y.fl[j].x)!=1)
97 o.a[i][k]=min(o.a[i][k],y.a[j][k]);
98 }
99 memcpy(y.a,o.a,sizeof(o.a));
100 memset(o.a,0x3f,sizeof(o.a));
101 for(int i=0;i<5;i++)
102 for(int j=0;j<5;j++)
103 for(int k=0;k<5;k++)o.a[i][k]=min(o.a[i][k],x.a[i][j]+y.a[j][k]);
104 return o;
105 }
106 void update(int k,int l,int r,int x,int y){
107 if (l==r){
108 tr[k].l=tr[k].r=y;
109 tr[k].len=1;
110 return;
111 }
112 if (x<=mid)update(L,l,mid,x,y);
113 else update(R,mid+1,r,x,y);
114 tr[k]=merge(tr[L],tr[R]);
115 }
116 int main(){
117 scanf("%d%d%d%d",&n,&m,&t,&l);
118 memset(head,-1,sizeof(head));
119 for(int i=1;i<=m;i++){
120 scanf("%d%d%d",&x,&y,&z);
121 add(x,y,z);
122 add(y,x,z);
123 }
124 for(int i=1;i<=n;i++)
125 for(int j=1;j<=n;j++)
126 for(int k=0;k<5;k++)
127 if (i==j)f[k][i][j]=path{-1,-1,0};
128 else f[k][i][j]=path{-1,-1,oo};
129 for(int i=0;i<E;i++){
130 dij(i);
131 for(int j=0;j<E;j++)dis[i][j]=d[j];
132 }
133 for(int i=1;i<=n;i++)
134 for(int j=1;j<=n;j++){
135 for(int x=head[i];x!=-1;x=edge[x].nex){
136 if (edge[x].to==j)f[0][i][j]=min(f[0][i][j],path{x,x,edge[x].len});
137 for(int y=head[j];y!=-1;y=edge[y].nex)
138 f[0][i][j]=min(f[0][i][j],path{x,y^1,dis[x][y^1]});
139 }
140 for(int x=head[i];x!=-1;x=edge[x].nex){
141 if ((edge[x].to==j)&&(x!=f[0][i][j].y))f[1][i][j]=min(f[1][i][j],path{x,x,edge[x].len});
142 for(int y=head[j];y!=-1;y=edge[y].nex)
143 if ((y^f[0][i][j].y)!=1)f[1][i][j]=min(f[1][i][j],path{x,y^1,dis[x][y^1]});
144 }
145 for(int x=head[i];x!=-1;x=edge[x].nex){
146 if ((edge[x].to==j)&&(x!=f[0][i][j].y)&&(x!=f[1][i][j].x))f[2][i][j]=min(f[2][i][j],path{x,x,edge[x].len});
147 for(int y=head[j];y!=-1;y=edge[y].nex)
148 if (((y^f[0][i][j].y)!=1)&&(x!=f[1][i][j].x))f[2][i][j]=min(f[2][i][j],path{x,y^1,dis[x][y^1]});
149 }
150 f[3][j][i]=path{f[1][i][j].y^1,f[1][i][j].x^1,f[1][i][j].d};
151 f[4][j][i]=path{f[2][i][j].y^1,f[2][i][j].x^1,f[2][i][j].d};
152 }
153 for(int i=1;i<=l;i++){
154 scanf("%d",&x);
155 update(1,1,l,i,x);
156 }
157 for(int i=1;i<=t;i++){
158 scanf("%d%d",&x,&y);
159 update(1,1,l,x,y);
160 ans=oo;
161 for(int j=0;j<5;j++)
162 for(int k=0;k<5;k++)ans=min(ans,tr[1].a[j][k]);
163 if (ans>=oo)ans=-1;
164 printf("%lld\n",ans);
165 }
166 }
[loj2842]野猪的更多相关文章
- creature_template
entry 生物唯一编号 modelid_A 联盟模型ID,参考creature_model_info modelid_A2 同上 modelid_H 部落模型ID,参考creature_model_ ...
- scales小谈grunt
Grunt是基于Node.js的项目构建工具.它可以自动运行你所设定的任务.Grunt拥有数量庞大的插件,几乎任何你所要做的事情都可以用Grunt实现. 一头野猪映入眼帘,意:咕噜声 中文网站:htt ...
- [ZZ] GTX760首测
再一次让AMD难做!NVIDIA新主力GTX760首测 1又见短板高端显卡,GTX760外观对比回顶部 [PConline评测]NVIDIA迅速的步伐真让人吃惊,短时间内拿出GTX780.GTX770 ...
- GTX 770 (GK 104)
上周的这个时候,NVIDIA GeForce 700系列的旗舰产品GTX 780正式发布,传闻已久的GTX 700家族终于来了!虽然没有任何新架构.新特性的旗舰卡发布总让人觉得少点什么.但从性能上来说 ...
- App Store--心酸的上线路,说说那些不可思议的被拒理由
yoyeayoyea 您的应用包括色情内容(色情交易,色情展示). 原因是我们的销售人员,把几张艺术照放在个人相册里(头像),换成卡通头像,通过. 颜小风 被拒很正常 一次通过不正常. 之前上线 ...
- 解决unity3d发布的网页游戏放到服务器上无法使用的问题
http://www.unity蛮牛.com/blog-2429-1226.html 第一次把unity3d发布的网页游戏放到服务器上(Win2003),发现无法使用.可以尝试以下办法. ...
- Unite Beijing 2015大型活动
摘要:2015年,我做的最疯狂的事情:网友见面会—去北京参加Unite Beijing 2015大会. 正文:记得,上次在北京参加大型活动还是2008年前–传统电信行业的巅峰时期:那时移动互联网.An ...
- [转载]Unity3D 访问Access数据库
在开始这个小教程之前呢,其实在网上你已经可以找到相关的资料了,但是我还是要把我自己做练习的一点东西分享出来.写这个教程的主要原因呢,是一个朋友在u3d的官网论坛里,找到了这个demo,但是在他使用的过 ...
- NOIWC2018 游记
day1 上午是自习,做了一些杂题,看了一下ppt,中午准备了一下行李,就出发了,提前了一个小时,谁知道被坑爹导航弄得居然到晚了一点 当走到这里的时候我愣住了 纠结了一分钟,直到有个boy走了进去,我 ...
随机推荐
- 学习使用Wpf开源的文本编辑器—smithhtmleditor
前言 本文主要介绍使用Wpf文本编辑器--smithhtmleditor. 编辑器使用 首先新建一个项目WpfEditor. 然后到Codeplex下载smithhtmleditor. 下载地址:ht ...
- JS 实现计算器功能
括号功能未实现,后续更 <!DOCTYPE html> <html lang="en"> <head> <meta charset=&qu ...
- 2020.10.17-pta天梯练习赛补题
7-5敲笨钟 微博上有个自称"大笨钟V"的家伙,每天敲钟催促码农们爱惜身体早点睡觉.为了增加敲钟的趣味性,还会糟改几句古诗词.其糟改的方法为:去网上搜寻压"ong&quo ...
- UE4蓝图AI角色制作(六)之行为树
13.行为树原理 AI最重要的环节就是行为树.我们将解释什么是行为树.为何它如此重要,以及构建行为树需要哪些元素. 借助行为树,我们可以轻松控制并显示AI的决策制定过程.行为树是一种将AI在场景中的决 ...
- DevOps 时代的高效测试之路
10 月 22 日,2021 届 DevOps 国际峰会在北京顺利召开,来自国内外的顶级技术专家共同畅谈 DevOps 体系与方法.过程与实践.工具与技术.CODING 测试及研发流程管理产品总监程胜 ...
- gridlayout在kv中的引用
from kivy.app import App from kivy.uix.gridlayout import GridLayout class GridLayoutWidget(GridLayou ...
- Java-基础-ArrayList
1. 简介 ArrayList 实现了 List 接口,其底层基于数组实现容量大小动态可变.既然是数组,那么元素存放一定是有序的,并允许包括 null 在内的所有元素. 每个 ArrayList 实例 ...
- Java:ConcurrentHashMap类小记-1(概述)
Java:ConcurrentHashMap类小记-1(概述) 对 Java 中的 ConcurrentHashMap类,做一个微不足道的小小小小记,分三篇博客: Java:ConcurrentHas ...
- Scrum Meeting 10
第10次例会报告 日期:2021年05月30日 会议主要内容概述: 目前组员均无暇软工,进展较慢. 一.进度情况 我们采用日报的形式记录每个人的具体进度,链接Home · Wiki,如下记录仅为保证公 ...
- 单片机I/O口推挽与开漏输出详解(力荐)
推挽输出:可以输出高,低电平,连接数字器件;推挽结构一般是指两个三极管分别受两互补信号的控制,总是在一个三极管导通的时候另一个截止. 开漏输出:输出端相当于三极管的集电极. 要得到高电平状态需要上拉电 ...