书接上回
14. 图论 E. Minimum Path
考虑这个路径权值的实质,就是将最大值不算,最小值算两次。我们直接将其拓展,改成任选一条边不算,一条边算两次,由贪心可知显然不会改变答案。于是将每个点拆成四个点,跑 dijkstra 即可。
Code
#include<bits/stdc++.h>
#define int long long
#define il inline
#define pb push_back
#define pii pair<int,int>
#define fir first
#define sec second
#define mp make_pair
using namespace std;
namespace asbt{
const int maxn=2e5+5;
int n,m,dis[maxn][4];
bool vis[maxn][4];
vector<pii> e[maxn];
priority_queue<pair<int,pii>> q;
int main(){ios::sync_with_stdio(0),cin.tie(0);cin>>n>>m;for(int i=1,u,v,w;i<=m;i++){cin>>u>>v>>w;e[u].pb(mp(v,w));e[v].pb(mp(u,w));}memset(dis,0x3f,sizeof(dis));dis[1][0]=0,q.push(mp(0,mp(1,0)));while(q.size()){int u=q.top().sec.fir,s=q.top().sec.sec;q.pop();if(vis[u][s]){continue;}vis[u][s]=1;for(pii i:e[u]){int v=i.fir,w=i.sec;if(!vis[v][s]&&dis[v][s]>dis[u][s]+w){dis[v][s]=dis[u][s]+w;q.push(mp(-dis[v][s],mp(v,s)));}if(!(s&1)&&!vis[v][s|1]&&dis[v][s|1]>dis[u][s]){dis[v][s|1]=dis[u][s];q.push(mp(-dis[v][s|1],mp(v,s|1)));}if(!(s&2)&&!vis[v][s|2]&&dis[v][s|2]>dis[u][s]+2*w){dis[v][s|2]=dis[u][s]+2*w;q.push(mp(-dis[v][s|2],mp(v,s|2)));}if(!s&&!vis[v][3]&&dis[v][3]>dis[u][s]+w){dis[v][3]=dis[u][s]+w;q.push(mp(-dis[v][3],mp(v,3)));}}}for(int i=2;i<=n;i++){cout<<dis[i][3]<<' ';}return 0;
}
}
signed main(){return asbt::main();}