joisc2018_l 题解
思路
先跳过这一部分。如果可以在可行复杂度内预处理出结构体
考虑线段树维护每个间隔。记录
可以构造
-
到 的最短路: 。 -
不经过
的最短路: 。 -
不经过
且不同于 的最短路: 。 -
不经过
且不同于 的最短路: 。
现在要求两点间不过第三点的最短路。厉害的是,可以把无向边拆除两条有向边当成点跑的最短路。
从每条边
然后枚举点
总复杂度
code
int n,m,t,l;
int head[maxn],tot=1;
struct nd{
int nxt,to,fr;ll w;
}e[maxn];
void add(int u,int v,ll w){e[++tot]={head[u],v,u,w};head[u]=tot;}
ll dis[maxn][maxn];
struct Dis{
int id;ll dis;
bool operator <(const Dis&tmp)const{return dis>tmp.dis;}
};
priority_queue<Dis> q;
bool vis[maxn];int bk[maxn];
void dij(int s){
for(int i=2;i<=tot;i++)dis[s][i]=inf;
memset(vis,0,sizeof(vis));memset(bk,0,sizeof(bk));
dis[s][s]=e[s].w;q.push({s,dis[s][s]});
// cout<<s<<"\n";
while(!q.empty()){
int u=q.top().id;q.pop();
if(vis[u])continue;vis[u]=1;
// cout<<u<<" "<<dis[s][u]<<"\n";
if(bk[e[u].to]){
if(dis[s][bk[e[u].to]]>dis[s][u]+e[bk[e[u].to]].w){
dis[s][bk[e[u].to]]=dis[s][u]+e[bk[e[u].to]].w;
q.push({bk[e[u].to],dis[s][bk[e[u].to]]});
}
bk[e[u].to]=-1;
}
if(!bk[e[u].to]){
for(int i=head[e[u].to];i;i=e[i].nxt){
int v=e[i].to;if(!bk[e[u].to]&&i==(u^1))continue;
// cout<<v<<"\n";
if(dis[s][i]>dis[s][u]+e[i].w){
dis[s][i]=dis[s][u]+e[i].w;
q.push({i,dis[s][i]});
}
}
bk[e[u].to]=u^1;
}
}
}
int a[maxm];
struct path{
ll dis;int x,y;
}mn[maxn][maxn][4];
path Min(path u,path v){if(u.dis<v.dis)return u;return v;}
struct mat{
ll v[4][4];
mat(){memset(v,0x3f,sizeof(v));}
}tree[maxm<<2];
mat merge(mat u,mat v,int mid){
mat res;
for(int i=0;i<4;i++){
for(int j=0;j<4;j++){
res.v[i][j]=inf;
for(int k=0;k<4;k++){
for(int l=0;l<4;l++){
if(mn[a[mid]][a[mid+1]][k].y!=mn[a[mid+1]][a[mid+2]][l].x)res.v[i][j]=min(res.v[i][j],u.v[i][k]+v.v[l][j]);
}
}
}
}
return res;
}
#define mid (l+r>>1)
#define ls nd<<1
#define rs nd<<1|1
void build(int nd,int l,int r){
if(l==r){
for(int i=0;i<4;i++)tree[nd].v[i][i]=mn[a[l]][a[l+1]][i].dis;
return ;
}
build(ls,l,mid),build(rs,mid+1,r);
tree[nd]=merge(tree[ls],tree[rs],mid);
}
void updata(int nd,int l,int r,int p){
if(l==r){
for(int i=0;i<4;i++)tree[nd].v[i][i]=mn[a[l]][a[l+1]][i].dis;
return ;
}
if(p<=mid)updata(ls,l,mid,p);
else updata(rs,mid+1,r,p);
tree[nd]=merge(tree[ls],tree[rs],mid);
}
void work(){
n=read();m=read();t=read();l=read();
for(int i=1;i<=m;i++){
int u=read(),v=read(),w=read();
add(u,v,w),add(v,u,w);
}
for(int i=1;i<=l;i++)a[i]=read();
for(int i=2;i<=tot;i++)dij(i);
for(int u=1;u<=n;u++){
for(int v=1;v<=n;v++)if(u!=v){
for(int i=0;i<4;i++)mn[u][v][i]={inf,0,0};
for(int i=head[u];i;i=e[i].nxt){
int uu=e[i].to;
for(int j=head[v];j;j=e[j].nxt){
int vv=e[j].to;
mn[u][v][0]=Min(mn[u][v][0],{dis[i][j^1],uu,vv});
}
}
for(int i=head[u];i;i=e[i].nxt){
int uu=e[i].to;
for(int j=head[v];j;j=e[j].nxt){
int vv=e[j].to;
if(uu!=mn[u][v][0].x&&vv!=mn[u][v][0].y)mn[u][v][1]=Min(mn[u][v][1],{dis[i][j^1],uu,vv});
}
}
for(int i=head[u];i;i=e[i].nxt){
int uu=e[i].to;
for(int j=head[v];j;j=e[j].nxt){
int vv=e[j].to;
if(uu!=mn[u][v][0].x&&vv!=mn[u][v][1].y)mn[u][v][2]=Min(mn[u][v][2],{dis[i][j^1],uu,vv});
}
}
for(int i=head[u];i;i=e[i].nxt){
int uu=e[i].to;
for(int j=head[v];j;j=e[j].nxt){
int vv=e[j].to;
if(uu!=mn[u][v][1].x&&vv!=mn[u][v][0].y)mn[u][v][3]=Min(mn[u][v][3],{dis[i][j^1],uu,vv});
}
}
}
}
build(1,1,l-1);
while(t--){
int u=read(),v=read();a[u]=v;
if(u>1)updata(1,1,l-1,u-1);
updata(1,1,l-1,u);
ll ans=inf;for(int i=0;i<4;i++)for(int j=0;j<4;j++)ans=min(ans,tree[1].v[i][j]);
if(ans>=inf)ans=-1;
printf("%lld\n",ans);
}
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具