Codeforces1473 E. Minimum Path(最短路+dp)

题意:

给定n个点m条边的带权无向图,
对于一条路径,距离定义为 s u m ( w ) − m a x ( w ) + m i n ( w ) sum(w)-max(w)+min(w) sum(w)max(w)+min(w),其中w是路径的边权集。
求点1到其他每个点的最短路。

数据范围:n,m<=2e5

解法:

-max(w)可以看作是可以免费走一条边,
+min(w)可以看作是必须额外走一条边.
令dp[i][j][k]表示点1到达点i,是否免费一条边,是否额外一条边的最小代价.
利用最短路算法进行dp的转移即可,显然最短路算法会智能的选择免费走max(w),额外走min(w)
最后d[i][1][1]就是答案.

code:

#include <bits/stdc++.h>
using namespace std;
#define int long long
#define PI pair<int,int>
const int maxm=2e5+5;
struct Node{
    
    
    int dist,i,j,k;
    friend bool operator<(const Node& a,const Node& b){
    
    
        return a.dist>b.dist;
    }
};
vector<PI>g[maxm];
int mark[maxm][2][2];
int d[maxm][2][2];
int n,m;
void dj(){
    
    
    for(int i=1;i<=n;i++){
    
    
        for(int j=0;j<2;j++){
    
    
            for(int k=0;k<2;k++){
    
    
                d[i][j][k]=1e18;
            }
        }
    }
    d[1][0][0]=0;
    priority_queue<Node>q;
    q.push({
    
    d[1][0][0],1,0,0});
    while(q.size()){
    
    
        int i=q.top().i;
        int j=q.top().j;
        int k=q.top().k;
        q.pop();
        if(mark[i][j][k])continue;
        mark[i][j][k]=1;
        for(auto p:g[i]){
    
    
            int nt=p.first,w=p.second;
            if(!mark[nt][j][k]&&d[nt][j][k]>d[i][j][k]+w){
    
    //正常走
                d[nt][j][k]=d[i][j][k]+w;
                q.push({
    
    d[nt][j][k],nt,j,k});
            }
            if(j==0){
    
    //免去这条边的花费
                if(!mark[nt][1][k]&&d[nt][1][k]>d[i][j][k]){
    
    
                    d[nt][1][k]=d[i][j][k];
                    q.push({
    
    d[nt][1][k],nt,1,k});
                }
            }
            if(k==0){
    
    //额外加上这条边的花费
                if(!mark[nt][j][1]&&d[nt][j][1]>d[i][j][k]+w+w){
    
    
                    d[nt][j][1]=d[i][j][k]+w+w;
                    q.push({
    
    d[nt][j][1],nt,j,1});
                }
            }
            if(j==0&&k==0){
    
    //免去这条边的花费,同时额外加上这条边的花费
                if(!mark[nt][1][1]&&d[nt][1][1]>d[i][j][k]+w){
    
    
                    d[nt][1][1]=d[i][j][k]+w;
                    q.push({
    
    d[nt][1][1],nt,1,1});
                }
            }
        }
    }
}
signed main(){
    
    
    ios::sync_with_stdio(0);
    cin>>n>>m;
    for(int i=1;i<=m;i++){
    
    
        int a,b,c;cin>>a>>b>>c;
        g[a].push_back({
    
    b,c});
        g[b].push_back({
    
    a,c});
    }
    dj();
    for(int i=2;i<=n;i++){
    
    
        cout<<d[i][1][1]<<' ';
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_44178736/article/details/112790223