E - Minimum Path
分层图最短路
第一个分层图
第0层就是按照题中给的点连边,从第0层到第1层我们连一条边权是0的边,从第1层到第2层连一条边权是原先边权2倍的边,当然第1层以及第2层之间按照原图连边。
第二个分层图
第0层就是按照题中给的点连边,从第0层到第1层我们连一条边权是原先边权2倍的边,从第1层到第2层连一条边权0的边,当然第1层以及第2层之间按照原图连边。
然后最终答案在两个分层图的第二层比较。如果从1到某个点只存在一条边,那么最短路应该与第0层的答案相同,再顺便比较一下即可。
为什么有两个分层图?
第一个分层图我们从0—>1层花费是0代表少经过一条边,从1—>2层花费原先两倍边权,两者结合代表用一条边的边权代替另一题边的边权。而这样建图表示最长边出现在最短边之前。
而第二个分层图代表最短边出现最长边之前。而所有点的最短路无非这两种情况。
对于一条路径我们没考虑减去最大值加上最小值,而是用一条路边替另一条边,而最短路径一定是最小的边代替最长的边
#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0)
#pragma GCC optimize(2)
#include<set>
#include<map>
#include<cmath>
#include<stack>
#include<queue>
#include<bitset>
#include<random>
#include<bitset>
#include<string>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<unordered_map>
#include<unordered_set>
using namespace std;
typedef long long ll;
typedef pair<ll,int> pli;
const int N=600010;
const int M=4000010;
int h1[N],h2[N],e[M],ne[M],idx;
int n,m;
ll w[M],d1[N],d2[N];
bool st[N];
void add(int h[],int a,int b,ll c)
{e[idx]=b;w[idx]=c;ne[idx]=h[a];h[a]=idx++;
}
void dijkstra(int h[],ll dist[])
{//memset(dist,0x3f,8*N);memset(st,0,sizeof st);dist[1]=0;priority_queue<pli,vector<pli>,greater<pli> >q;q.push({0,1});while(q.size()){ll d=q.top().first,t=q.top().second;q.pop();if(st[t]) continue;st[t]=1;for(int i=h[t];i!=-1;i=ne[i]){int j=e[i];if(dist[j]>d+w[i]) {dist[j]=d+w[i];q.push({dist[j],j});}}}
}int main()
{IO;int T=1;//cin>>T;while(T--){cin>>n>>m;memset(h1,-1,sizeof h1);memset(h2,-1,sizeof h2);memset(d1,0x3f,sizeof d1);memset(d2,0x3f,sizeof d2);while(m--){int a,b,c;cin>>a>>b>>c;add(h1,a,b,c),add(h1,b,a,c);add(h1,a+n,b+n,c),add(h1,b+n,a+n,c);add(h1,a+2*n,b+2*n,c),add(h1,b+2*n,a+2*n,c);add(h1,a,b+n,0);add(h1,b,a+n,0);add(h1,a+n,b+2*n,2*c);add(h1,b+n,a+2*n,2*c);add(h2,a,b,c),add(h2,b,a,c);add(h2,a+n,b+n,c),add(h2,b+n,a+n,c);add(h2,a+2*n,b+2*n,c),add(h2,b+2*n,a+2*n,c);add(h2,a,b+n,2*c);add(h2,b,a+n,2*c);add(h2,a+n,b+2*n,0);add(h2,b+n,a+2*n,0);}dijkstra(h1,d1);dijkstra(h2,d2);for(int i=2;i<=n;i++)cout<<min(min(d1[i],d1[i+2*n]),d2[i+2*n])<<' ';cout<<'\n';}return 0;
}
可惜和队友想出做法的时候就剩10分钟了,没能完成可惜可惜