E. Paired Payment 分层图最短路

E. Paired Payment 分层图最短路

题目大意:

给你 n 个点,m条边的图,每次至少走2步,权值即为两步经过的边的权值之和的平方,问从1点出发到达 (t) 点的最短距离。

题解:

分层图最短路

定义 (dp[i][x]) 表示到第 (i) 个节点,上一条边的权值是 (j) 的最优解。

#include <bits/stdc++.h>
#define inf 0x3f3f3f3f
using namespace std;
typedef long long ll;
const int maxn = 2e5+10;
int cnt,to[maxn*2],nxt[maxn*2],head[maxn],w[maxn*2];
void add(int u,int v,int c){
    ++cnt,to[cnt] = v,w[cnt] = c,nxt[cnt] = head[u],head[u] = cnt;
}
int dis[maxn][55];
bool vis[maxn][55];
struct node{
    int u,pre,d;
    node(int u=0,int pre=0,ll d=0):u(u),pre(pre),d(d){}
    bool operator<(const node &a)const{
        return a.d<d;
    }
};
priority_queue<node>que;
void dij(int s){
    memset(vis,0,sizeof(vis));
    memset(dis,inf,sizeof(dis));
    dis[s][0] = 0;
    que.push(node(s,0,0));
    while(!que.empty()){
        node x = que.top();que.pop();
        int u = x.u,pre = x.pre;
//        printf("u = %d pre = %d dis = %lld
",u,pre,x.d);
        if(vis[u][pre]) continue;
        vis[u][pre] = true;
        for(int i=head[u];i;i=nxt[i]){
            int v = to[i],c = w[i];
            if(pre==0){
                if(dis[v][c]>dis[u][pre]){
                    dis[v][c] = dis[u][pre];
                    que.push(node(v,c,dis[v][c]));
                }
            }
            else{
                int val = (c+pre)*(c+pre);
                if(dis[v][0]>dis[u][pre]+val){
                    dis[v][0] = dis[u][pre] + val;
                    que.push(node(v,0,dis[v][0]));
                }
            }
        }
    }
}
int main(){
    int n,m;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++){
        int u,v,c;
        scanf("%d%d%d",&u,&v,&c);
        add(u,v,c);
        add(v,u,c);
    }
    dij(1);
    for(int i=1;i<=n;i++){
        if(dis[i][0]>=inf) printf("-1");
        else printf("%d",dis[i][0]);
        if(i==n) printf("
");
        else printf(" ");
    }
    return 0;
}
原文地址:https://www.cnblogs.com/EchoZQN/p/14491143.html