分层图+最短路算法
对于题目当中的条件进行转化,相当于允许一条边代价为0,一条边代价为两倍,且必须要两种情况都使用。
因此考虑建立分层图,这样的话,分成四层,就能够先0后2倍,先两倍后0,两种情况都能表达了
此外,由于由于存在一条边即作为最小值也作为最大值,我们要连一条直接从1到第四层的边
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int N=4e6+10; const int mod=1e9+7; int h[N],ne[N],e[N],w[N],idx; ll dis[N]; int st[N]; int n,m; void add(int a,int b,int c){ e[idx]=b,ne[idx]=h[a],w[idx]=c,h[a]=idx++; } void add1(int a,int b,int c){ add(a,b,c),add(a+n,b+n,c),add(a+2*n,b+2*n,c),add(a+3*n,b+3*n,c); add(a,b+n,0),add(a+2*n,b+3*n,0); add(a,b+2*n,2*c),add(a+n,b+3*n,2*c); add(a,b+3*n,c); } struct node{ int id; ll dis; bool operator <(const node &t) const{ return dis>t.dis; } }; void dij(){ priority_queue<node> q; memset(dis,0x3f,sizeof dis); dis[1]=0; q.push({1,0}); while(q.size()){ auto t=q.top(); q.pop(); if(st[t.id]) continue; st[t.id]=1; for(int i=h[t.id];i!=-1;i=ne[i]){ int j=e[i]; if(dis[j]>dis[t.id]+w[i]){ dis[j]=dis[t.id]+w[i]; q.push({j,dis[j]}); } } } } int main(){ ios::sync_with_stdio(false); memset(h,-1,sizeof h); int i; cin>>n>>m; for(i=1;i<=m;i++){ int a,b,c; cin>>a>>b>>c; add1(a,b,c); add1(b,a,c); } dij(); for(i=2+3*n;i<=4*n;i++){ cout<<dis[i]<<" "; } cout<<endl; }