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

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

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

但由于我们所预处理的并不能与实际的$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. 题解 [HAOI2017]方案数

    题目传送门 Solution 我们没有障碍的时候很好做,直接设 \(f_{i,j,k}\) 表示到 \((x,y,z)\) \(x\) 有 \(i\) 位为 \(1\),\(y\) 有 \(j\) 位 ...

  2. SpringBoot-集成SpringSecurity

    在 Web 开发中,安全一直是非常重要的一个方面. 安全虽然属于应用的非功能性需求,但是从应用开发的第一天就应该把安全相关的因素考虑进来,并在整个应用的开发过程中. Spring Security官网 ...

  3. Java(35)IO特殊操作流&Properties集合

    作者:季沐测试笔记 原文地址:https://www.cnblogs.com/testero/p/15228454.html 博客主页:https://www.cnblogs.com/testero ...

  4. .Net Core微信服务商二次进件

    最近商城进行微信服务商二次进件的开发,大致有几个点 一,服务商签名 二,服务商证书获取 三,图片上传 四,敏感信息加密 五,查询进件状态 除此之外,就是进件信息的拼装 电商二级商户进件申请单-状态流转 ...

  5. Java中的函数式编程(四)方法引用method reference

    写在前面 我们已经知道,lambda表达式是一个匿名函数,可以用lambda表达式来实现一个函数式接口.   很自然的,我们会想到类的方法也是函数,本质上和lambda表达式是一样的,那是否也可以用类 ...

  6. python flask1

    以这个服务端代码为例,简单了解一下flask的运用. 1.app = Flask(__name__)记住就好了 2.@app.route("/")记住就好了:注意括号里的是调用这个 ...

  7. 基于自定义Validator来验证枚举类型

    基于自定义Validator来验证枚举类型 一.背景 二.技术要点 三.实现一个自定义枚举校验. 1.需求. 2.实现步骤 1.自定义一个 Sex 枚举. 2.自定义一个 Enum 注解 3.编写具体 ...

  8. rabbitmq生产者消息确认

    在使用 RabbitMQ 的时候,有时候当我们生产者发送一条消息到 RabbitMQ 服务器后,我们 生产者想知道消息是否到达了 RabbitMQ 服务器上.这个时候我们应该如何处理? 针对上述问题, ...

  9. 表单编辑时el-form的validate方法执行无效,阻塞代码运行 - Element UI踩坑记录

    今天在用element-ui写管理后台需求时,遇到一个奇怪的问题 一个正常带校验的表单,在新增列表数据时表单校验功能正常: 但是在新增之后再去编辑数据时,表单校验却失效了,甚至阻塞了后续的代码执行,控 ...

  10. 关于linux下编译的几点知识

    1.-L.-rpath 和 rpath_link的区别 参考博客文章:https://www.cnblogs.com/candl/p/7358384.html (1)-rpath和-rpath-lin ...