1. 程式人生 > 其它 >Codeforces-1473 E. Minimum Path(分層圖(多維)最短路)

Codeforces-1473 E. Minimum Path(分層圖(多維)最短路)

技術標籤:# codeforces# 最短路

題意:
一條路徑的花費為在這裡插入圖片描述
求1點到其他所有點路徑的最小花費。

思路:
每個路徑可以分出兩種操作:減掉一條邊,加上一條邊。
那麼定義 d i s [ i ] [ 0 / 1 ] [ 0 / 1 ] dis[i][0/1][0/1] dis[i][0/1][0/1]代表1到 i i i路徑的最小花費,以及包括第一次操作的使用情況,第二次操作的使用情況。
然後就 d i j dij dij轉移就好了。

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std; typedef long long ll; const int maxn = 2e5 + 7; const int INF = 0x3f3f3f3f; ll dis[maxn][2][2]; bool vis[maxn][2][2]; int head[maxn],nex[maxn * 2],to[maxn * 2],val[maxn * 2],tot; struct Node { int x,y,z; ll v; bool operator < (const Node &rhs) const { return
v > rhs.v; } }; void add(int x,int y,int z) { to[++tot] = y; nex[tot] = head[x]; val[tot] = z; head[x] = tot; } void dijkstra() { priority_queue<Node>q; q.push({1,0,0,0}); memset(dis,0x3f,sizeof(dis)); dis[1][0][0] = 0; while(!q.empty()) { Node now =
q.top();q.pop(); int x = now.x,y = now.y,z = now.z; if(vis[x][y][z]) continue; vis[x][y][z] = 1; for(int i = head[x];i;i = nex[i]) { int v = to[i],w = val[i]; if(dis[v][y][z] > dis[x][y][z] + w) { dis[v][y][z] = dis[x][y][z] + w; q.push({v,y,z,dis[v][y][z]}); } if(!y) { if(dis[v][y ^ 1][z] > dis[x][y][z]) { dis[v][y ^ 1][z] = dis[x][y][z]; q.push({v,y ^ 1,z,dis[v][y ^ 1][z]}); } } if(!z) { if(dis[v][y][z ^ 1] > dis[x][y][z] + w * 2) { dis[v][y][z ^ 1] = dis[x][y][z] + w * 2; q.push({v,y,z ^ 1,dis[v][y][z ^ 1]}); } } if(!y && !z) { if(dis[v][y ^ 1][z ^ 1] > dis[x][y][z] + w) { dis[v][y ^ 1][z ^ 1] = dis[x][y][z] + w; q.push({v,y ^ 1,z ^ 1,dis[v][y ^ 1][z ^ 1]}); } } } } } int main() { int n,m;scanf("%d%d",&n,&m); for(int i = 1;i <= m;i++) { int x,y,z;scanf("%d%d%d",&x,&y,&z); add(x,y,z);add(y,x,z); } dijkstra(); for(int i = 2;i <= n;i++) { printf("%lld ",dis[i][1][1]); } return 0; }