CF1473E Minimum Path(分层图+最短路)

分层图+最短路算法

对于题目当中的条件进行转化,相当于允许一条边代价为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;
}
View Code

 

posted @ 2021-03-30 21:38  朝暮不思  阅读(65)  评论(0编辑  收藏  举报