题目链接:https://codeforces.com/contest/1473/problem/E
题目可以转化成:路径上有一条边权被计算两次,有一条边权被忽略的最短路
设 (dp[i][0/1][0/1]) 表示到 (i) 的路径上有无边被忽略,有无边被计算两次时的最短路,暴力转移即可
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<ll, ll> P;
typedef pair<P, P> PP;
#define mp make_pair
const int maxn = 200010;
int n, m;
ll dis[maxn][2][2];
int vis[maxn][2][2];
int h[maxn], cnt = 0;
struct E{
int to, next;
ll cost;
}e[maxn << 1];
void add(int u, int v, ll w){
e[++cnt].to = v;
e[cnt].cost = w;
e[cnt].next = h[u];
h[u] = cnt;
}
void dij(){
priority_queue<PP, vector<PP>, greater<PP>> q;
for(int i = 1 ; i <= n ; ++i){
for(int j = 0 ; j <= 1 ; ++j){
for(int k = 0 ; k <= 1 ; ++k){
dis[i][j][k] = 1e16;
vis[i][j][k] = 0;
}
}
}
dis[1][0][0] = 0;
q.push(mp(mp(dis[1][0][0], 1), mp(0, 0)));
// for(int i = h[1] ; i != -1 ; i = e[i].next){
// int v = e[i].to;
// dis[v][1][1] = e[i].cost;
// }
while(!q.empty()){
PP pp = q.top(); q.pop();
int u = pp.first.second;
int x = pp.second.first, y = pp.second.second;
// printf("%d %d %d
", u, x, y);
if(vis[u][x][y]) continue;
vis[u][x][y] = 1;
for(int i = h[u] ; i != -1 ; i = e[i].next){
int v = e[i].to;
ll w = e[i].cost;
if(dis[u][x][y] + w < dis[v][x][y]){
dis[v][x][y] = dis[u][x][y] + w;
q.push(mp(mp(dis[v][x][y], v), mp(x, y)));
}
if(x == 0){
if(dis[u][x][y] < dis[v][1][y]){
dis[v][1][y] = dis[u][x][y];
q.push(mp(mp(dis[v][1][y], v), mp(1, y)));
}
}
if(y == 0){
if(dis[u][x][y] + 2ll * w < dis[v][x][1]){
dis[v][x][1] = dis[u][x][y] + 2ll * w;
q.push(mp(mp(dis[v][x][1], v), mp(x, 1)));
}
}
if(x == 0 && y == 0){
if(dis[u][x][y] + w < dis[v][1][1]){
dis[v][1][1] = dis[u][x][y] + w;
q.push(mp(mp(dis[v][1][1], v), mp(1, 1)));
}
}
}
}
for(int i = 2 ; i <= n ; ++i) {
printf("%lld ", dis[i][1][1]);
} printf("
");
}
ll read(){ ll s = 0, f = 1; char ch = getchar(); while(ch < '0' || ch > '9'){ if(ch == '-') f = -1; ch = getchar(); } while(ch >= '0' && ch <= '9'){ s = s * 10 + ch - '0'; ch = getchar(); } return s * f; }
int main(){
memset(h, -1, sizeof(h));
n = read(), m = read();
int u, v; ll w;
for(int i = 1 ; i <= m ; ++i){
u = read(), v = read(), w = read();
add(u, v, w), add(v, u, w);
}
dij();
return 0;
}