慢点做,有收获就行!
E. Roadblocks
题意:从1~n的次短路
范围:n<=5000,m<=100000
分析:
两种情况:
-
把道路分成三段:
dis(1,u)+(u,v)+dis(u,w)
-
在最短路上重复走:
dis(1,n)+其中一条:(u,v)->(v,u)->(u,v)
取其中较小的
显然跑两遍Dij
即可
细节:
如果分三段,(u,v)
不能在最短路上
两段最短路不能有重复(1到x的路径不能和y到n的路径重复)
#include<bits/stdc++.h>
using namespace std;
#define ll long long
ll n,m,dis[5005][2],xx[1000000],yy[1000000],zz[1000000];
ll head[1000000],tot;
struct nood{
ll v;
ll w;
ll nxt;
}es[1000000];
void adde(ll x,ll y,ll w){
es[++tot].v=y;es[tot].w=w;es[tot].nxt=head[x];head[x]=tot;
es[++tot].v=x;es[tot].w=w;es[tot].nxt=head[y];head[y]=tot;
}
void dij(ll st,ll js){
priority_queue< pair<ll,ll>,vector<pair<ll,ll> >,greater<pair<ll,ll> > > q;
//q.push({0,0});//dis,编号
q.push(make_pair(0,st));
dis[st][js]=0;
while(!q.empty()){
pair<ll,ll>vv=q.top();
ll bh=vv.second;//编号
ll di=vv.first;//dis
q.pop();
if(di==dis[bh][js]){
for(int i=head[bh];i;i=es[i].nxt){
ll v=es[i].v;
if(dis[v][js]>es[i].w+dis[bh][js]){
q.push(make_pair(es[i].w+dis[bh][js],v));
dis[v][js]=es[i].w+dis[bh][js];
}
}
}
}
}
int main(){
cin>>n>>m;
ll x,y,z;
for(int i=1;i<=m;i++){
cin>>x>>y>>z;
adde(x,y,z);
xx[i]=x;
yy[i]=y;
zz[i]=z;
}
memset(dis,0x7f,sizeof(dis));
dij(1,0);
ll maxx=dis[n][0];
ll anss=1e18;
dij(n,1);
for(int i=1;i<=m;i++){
if(dis[xx[i]][0]+dis[yy[i]][1]>dis[xx[i]][1]+dis[yy[i]][0]){//两段不能有重复
swap(xx[i],yy[i]);
}
ll ss=dis[xx[i]][0]+dis[yy[i]][1];
if(ss+zz[i]!=maxx){//不在最短路上
anss=min(anss,ss+zz[i]);
}
}
for(int i=1;i<=m;i++){
if(dis[xx[i]][0]+dis[yy[i]][1]>dis[xx[i]][1]+dis[yy[i]][0]){//两段不能有重复
swap(xx[i],yy[i]);
}
ll ss=dis[xx[i]][0]+dis[yy[i]][1];
if(ss+zz[i]==maxx){//在最短路上
anss=min(anss,ss+zz[i]*3);
}
}
cout<<anss;
}
标签:ll,Roadblocks,tot,js,xx,es,dis From: https://www.cnblogs.com/Misty-post/p/18434202