圖論:次短路
阿新 • • 發佈:2020-08-17
注意:此次短路可以走重邊
點選檢視程式碼
/* 次短路: 邊可以重複走 1.以1為起點跑最短路,以n為起點跑最短路。 2.列舉每一條邊,次短路只可能是兩種情況: (1)最短路上的最短的一條邊跑三次 (2)除了最短路外的其他能到n的次短路 */ #include <bits/stdc++.h> using namespace std; const int maxn=1e5+10; const int inf=0x3f3f3f3f; typedef long long ll; typedef pair<int,int> pii; int n,m; int head[maxn],cnt=0; struct edge{ int u,v,next; int w; }e[maxn<<2]; void add(int u,int v,int w){ e[cnt].u=u;e[cnt].v=v;e[cnt].w=w;e[cnt].next=head[u];head[u]=cnt++; } void init(){ memset(head,-1,sizeof(head));cnt=0; } int dis1[maxn],dis2[maxn]; bool vis[maxn]; void dij(int s,int d[]){ for (int i=0;i<=n;i++) d[i] = inf; memset(vis,0,sizeof(vis)); d[s]=0; priority_queue<pii,vector<pii>,greater<pii> > q; q.push({d[s],s}); while(!q.empty()){ int u=q.top().second; q.pop(); if(vis[u]) continue; vis[u]=1; for (int i=head[u];~i;i=e[i].next){ int v=e[i].v,w=e[i].w; if(d[v]>d[u]+w){ d[v]=d[u]+w; q.push({d[v],v}); } } } } int main(){ init(); scanf("%d%d",&n,&m); for (int i=1;i<=m;i++){ int u,v,w; scanf("%d%d%d",&u,&v,&w); u++;v++; add(u,v,w);add(v,u,w); } dij(1,dis1);dij(n,dis2); int ans1=dis1[n],ans2=inf; int mi = inf; for (int i=0;i<cnt;i++){ int u=e[i].u,v=e[i].v; int w=e[i].w; if(dis1[u]+dis2[v]+w > ans1) ans2=min(ans2,dis1[u]+dis2[v]+w);//大於最短路的路徑中的最小的 if(dis1[u]+dis2[v]+w == ans1) mi=min(mi,w);//找最短路中的最小的一條邊 } printf("%d\n",min(ans2,ans1+mi*2)); return 0; }