首先,并不一定走“除了上一次来的边”以外的最短路,但考虑“除了上一次来的边”以外的最短路和次短路(这里的次短路指最后一条边与最短路不同的“最短路”),必然是走这两者之一

(”除了上一次来的边“指第一步不走上一次来的边)

证明很显然,因为如果最短路不好必然是因为下一次需要先走最短路那条边,那么这次走次短路即可

但由于我们所预处理的并不能与实际的$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)$,可以通过

  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]野猪的更多相关文章

  1. creature_template

    entry 生物唯一编号 modelid_A 联盟模型ID,参考creature_model_info modelid_A2 同上 modelid_H 部落模型ID,参考creature_model_ ...

  2. scales小谈grunt

    Grunt是基于Node.js的项目构建工具.它可以自动运行你所设定的任务.Grunt拥有数量庞大的插件,几乎任何你所要做的事情都可以用Grunt实现. 一头野猪映入眼帘,意:咕噜声 中文网站:htt ...

  3. [ZZ] GTX760首测

    再一次让AMD难做!NVIDIA新主力GTX760首测 1又见短板高端显卡,GTX760外观对比回顶部 [PConline评测]NVIDIA迅速的步伐真让人吃惊,短时间内拿出GTX780.GTX770 ...

  4. GTX 770 (GK 104)

    上周的这个时候,NVIDIA GeForce 700系列的旗舰产品GTX 780正式发布,传闻已久的GTX 700家族终于来了!虽然没有任何新架构.新特性的旗舰卡发布总让人觉得少点什么.但从性能上来说 ...

  5. App Store--心酸的上线路,说说那些不可思议的被拒理由

    yoyeayoyea 您的应用包括色情内容(色情交易,色情展示). 原因是我们的销售人员,把几张艺术照放在个人相册里(头像),换成卡通头像,通过.    颜小风 被拒很正常 一次通过不正常. 之前上线 ...

  6. 解决unity3d发布的网页游戏放到服务器上无法使用的问题

    http://www.unity蛮牛.com/blog-2429-1226.html 第一次把unity3d发布的网页游戏放到服务器上(Win2003),发现无法使用.可以尝试以下办法.       ...

  7. Unite Beijing 2015大型活动

    摘要:2015年,我做的最疯狂的事情:网友见面会—去北京参加Unite Beijing 2015大会. 正文:记得,上次在北京参加大型活动还是2008年前–传统电信行业的巅峰时期:那时移动互联网.An ...

  8. [转载]Unity3D 访问Access数据库

    在开始这个小教程之前呢,其实在网上你已经可以找到相关的资料了,但是我还是要把我自己做练习的一点东西分享出来.写这个教程的主要原因呢,是一个朋友在u3d的官网论坛里,找到了这个demo,但是在他使用的过 ...

  9. NOIWC2018 游记

    day1 上午是自习,做了一些杂题,看了一下ppt,中午准备了一下行李,就出发了,提前了一个小时,谁知道被坑爹导航弄得居然到晚了一点 当走到这里的时候我愣住了 纠结了一分钟,直到有个boy走了进去,我 ...

随机推荐

  1. C#开发BIMFACE系列42 服务端API之图纸对比

    BIMFACE二次开发系列目录     [已更新最新开发文章,点击查看详细] 在我的前一篇博客<C#开发BIMFACE系列42 服务端API之图纸对比>中详细介绍了BIMFACE服务端接口 ...

  2. 题解 「CTSC2018暴力写挂」

    题目传送门 题目大意 给出两个大小为 \(n\) 的树,求出: \[\max\{\text{depth}(x)+\text{depth}(y)-\text{depth}(\text{LCA}(x,y) ...

  3. 洛谷3320 SDOI2015寻宝游戏(set+dfs序)(反向迭代器的注意事项!)

    被\(STL\)坑害了一个晚上,真的菜的没救了啊. 准确的说是一个叫\(reverse\ iterator\)的东西,就是我们经常用的\(rbegin()\) 有一个非常重要的性质 在反向迭代器中,+ ...

  4. 【转载】如何从零开始开发一款嵌入式产品(20年的嵌入式经验分享学习,来自STM32神舟系列开发板设计师的总结

    [好文章值得分享,摘自作者:jesse] 来源:www.armjishu.com作者:jesse转载请注明出处 我的另一篇文章:<STM32嵌入式入门必看之文章-----介绍非常详细!(学STM ...

  5. 【JAVA】【作业向】第一题:本学期一班级有n名学生,m门课程。现要求对每门课程的成绩进行统计:平均成绩、最高成绩、最低成绩,并统计考试成绩的分布律。

    1.预备知识:动态数组Array实现: 2.解题过程需要理解的知识:吧唧吧唧吧唧吧唧 不想做了 就用了最简单的方法 和c语言类似 java版本 `import java.util.Scanner; / ...

  6. AIApe问答机器人项目Scrum Meeting博客汇总

    荡起双桨 Scrum Meeting 博客汇总 一.Alpha阶段 AIApe问答机器人Scrum Meeting 4.23 AIApe问答机器人Scrum Meeting 4.25 AIApe问答机 ...

  7. [Beta]the Agiles Scrum Meeting 2

    会议时间:2020.5.11 20:00 1.每个人的工作 今天已完成的工作 成员 已完成的工作 yjy 修复bug将自动评测改为异步HTTP请求 tq 实现查看.删除测试点功能的后端将自动评测改为异 ...

  8. Spring Cloud Gateway 网关限流

    Spring Cloud Gateway 限流 一.背景 二.实现功能 三.网关层限流 1.使用默认的redis来限流 1.引入jar包 2.编写配置文件 3.网关正常响应 4.网关限流响应 2.自定 ...

  9. 零基础入门stm32基本定时器详解

    一.基本定时器介绍 在STM32中,基本定时器有TIM6.TIM7等.基本定时器主要包含时基单元,提供16位的计数,能计数0~65535.基本定时器除了计数功能以外,还能输出给DAC模块一个TRGO信 ...

  10. 基于SpringBoot项目MyBatis分页插件实现分页总结

    前言 在使用Mybatis时,最头痛的就是写分页了,需要先写一个查询count的select语句,然后再写一个真正分页查询的语句,当查询条件多了之后,会发现真的不想花双倍的时间写 count 和 se ...