codeforces1473 E.Minimum Path(分层图最短路)

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

猜你喜欢

转载自blog.csdn.net/Fighting_Peter/article/details/112666260