题解:AT_joi2020ho_d オリンピックバス (Olympic Bus)
发现这是个
对于图中的一条边
枚举
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=5e5+10,INF=1e18;
vector<array<int,4>> e[N];
int vis[210],n,m;
int spos,tmpd[210];
int mp[3][N],dist[210][210],to[210];
void dij(int s,int ops,int dis[]){
for(int i=1;i<=n;i++) dis[i]=INF,vis[i]=to[i]=0;
dis[s]=0;
for(int i=1;i<=n;i++){
int u=-1;
for(int j=1;j<=n;j++) if(!vis[j]&&(u==-1||dis[j]<dis[u])) u=j;
vis[u]=1;
for(auto [v,c,pos,flg]:e[u])
if(((flg==0&&pos==spos)||(flg==1&&pos!=spos))&&!vis[v]&&dis[u]+c<dis[v])
dis[v]=dis[u]+c,to[v]=pos;
}
for(int v=1;v<=n;v++) if(to[v]) mp[ops][to[v]]=1;
}
array<int,5> edge[N];
signed main(){
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
cin>>n>>m;
for(int i=1;i<=m;i++){
int u,v,c,d;cin>>u>>v>>c>>d;
e[u].push_back({v,c,i,1});
e[v].push_back({u,c,i,0});
edge[i]={u,v,c,d,i};
}
for(int i=1;i<=n;i++){
if(i==1) dij(1,0,dist[1]);
else if(i==n) dij(n,1,dist[n]);
else dij(i,2,dist[i]);
}
int ans=dist[1][n]+dist[n][1];
for(int i=1;i<=m;i++){
auto [u,v,c,d,pos]=edge[i];
int nd1,nd2;
if(mp[0][pos]) spos=i,dij(1,2,tmpd),nd1=tmpd[n];
else nd1=min(dist[1][n],dist[1][v]+dist[u][n]+c);
if(mp[1][pos]) spos=i,dij(n,2,tmpd),nd2=tmpd[1];
else nd2=min(dist[n][1],dist[n][v]+dist[u][1]+c);
ans=min(ans,nd1+nd2+d);
}
cout<<((ans>=INF)?-1:ans);
return 0;
}
::::