题目链接:https://codeforces.com/problemset/problem/1473/E
dis[u][c1][c2]
表示到达顶点 \(u\) 有无经过最短边(\(c1\) 标记)有无经过最长边(\(c2\) 标记)时的最短路。
示例程序:
#include <bits/stdc++.h>
using namespace std;
const int maxn = 2e5 + 5;int n, m;
long long dis[maxn][2][2];
bool vis[maxn][2][2];struct Node {int u, c1, c2;long long dis;bool operator < (const Node &b) const {return dis > b.dis;}
};struct Edge {int v, w;
};
vector<Edge> g[maxn];void dijkstra() {for (int i = 1; i <= n; i++)for (int j = 0; j < 2; j++)for (int k = 0; k < 2; k++)dis[i][j][k] = 1ll<<60;dis[1][0][0] = 0;priority_queue<Node> que;que.push({1, 0, 0, 0});while (!que.empty()) {Node nd = que.top();que.pop();int u = nd.u, c1 = nd.c1, c2 = nd.c2;long long _dis = nd.dis;if (vis[u][c1][c2]) continue;vis[u][c1][c2] = true;for (auto e : g[u]) {int v = e.v, w = e.w;if (dis[v][c1][c2] > dis[u][c1][c2] + w) {dis[v][c1][c2] = dis[u][c1][c2] + w;que.push({v, c1, c2, dis[v][c1][c2]});}if (!c1) {if (dis[v][c1+1][c2] > dis[u][c1][c2] + 2 * w) {dis[v][c1+1][c2] = dis[u][c1][c2] + 2 * w;que.push({v, c1+1, c2, dis[v][c1+1][c2]});}}if (!c2) {if (dis[v][c1][c2+1] > dis[u][c1][c2]) {dis[v][c1][c2+1] = dis[u][c1][c2];que.push({v, c1, c2+1, dis[v][c1][c2+1]});}}if (!c1 && !c2) {if (dis[v][c1+1][c2+1] > dis[u][c1][c2] + w) {dis[v][c1+1][c2+1] = dis[u][c1][c2] + w;que.push({v, c1+1, c2+1, dis[v][c1][c2]});}}}}
}int main() {scanf("%d%d", &n, &m);for (int i = 0; i < m; i++) {int u, v, w;scanf("%d%d%d", &u, &v, &w);g[u].push_back({v, w});g[v].push_back({u, w});}dijkstra();for (int i = 2; i <= n; i++)printf("%lld ", dis[i][1][1]);return 0;
}