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分钟了,没能完成可惜可惜