codeforces 1473 E

题目链接: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;
}
原文地址:https://www.cnblogs.com/tuchen/p/14287126.html