题目大意:有$n(nleqslant10^4)$个点,$m(mleqslant10^5)$条边的无向图,每个点有一个属性$A/B$,要求$|cnt_A-cnt_B|leqslant k(kleqslant10)$,问$S o T$最短路径
题解:把每个点拆成$2k+1$个点,分别标号为$[-k,k]$,表示到这$cnt_A-cnt_B$的值,跑最短路即可。
卡点:各种地方没有把$n$改成$n(2k+1)$
C++ Code:
#include <cstdio> #include <cstring> #include <algorithm> #include <iostream> #define maxn (10010 * 21) #define maxm (100010 * 21) int head[maxn], cnt; struct Edge { int to, nxt, w; } e[maxm << 1]; inline void addedge(int a, int b, int c) { e[++cnt] = (Edge) { b, head[a], c }; head[a] = cnt; } int n, m, k, K, S, T; namespace Graph { int V[maxn << 2]; long long dis[maxn]; inline int getmin(int a, int b) { return dis[a] < dis[b] ? a : b; } void modify(int rt, int l, int r, int p, int num) { if (l == r) { V[rt] = num; return ; } const int mid = l + r >> 1; if (p <= mid) modify(rt << 1, l, mid, p, num); else modify(rt << 1 | 1, mid + 1, r, p, num); V[rt] = getmin(V[rt << 1], V[rt << 1 | 1]); } long long dijkstra(int S, int T) { const int N = n * K + 1; memset(dis, 0x3f, sizeof dis); memset(V, 0, sizeof V); dis[S] = 0, modify(1, 1, N, S, S); for (int TIM = n * K + 1; TIM; --TIM) { int u = V[1]; modify(1, 1, N, u, 0); for (int i = head[u]; i; i = e[i].nxt) { int v = e[i].to; if (dis[v] > dis[u] + e[i].w) { dis[v] = dis[u] + e[i].w; modify(1, 1, N, v, v); } } } return dis[T]; } } int TIM, w[maxn]; int main() { std::ios::sync_with_stdio(false), std::cin.tie(0), std::cout.tie(0); std::cin >> TIM; while (TIM --> 0) { std::cin >> n >> m >> k; K = 2 * k + 1; for (int i = 1, x; i <= n; ++i) std::cin >> x, w[i] = x - 1; for (int i = 0, a, b, c; i < m; ++i) { std::cin >> a >> b >> c; --a, --b; for (int j = 2; j <= K; ++j) { if (w[b + 1]) addedge(a * K + j - 1, b * K + j, c); else addedge(a * K + j, b * K + j - 1, c); if (w[a + 1]) addedge(b * K + j - 1, a * K + j, c); else addedge(b * K + j, a * K + j - 1, c); } } std::cin >> S >> T; --S, --T; for (int j = 1; j <= K; ++j) addedge(T * K + j, n * K + 1, 0); int St = S * K + k + 1; if (w[S + 1]) ++St; else --St; long long ans = Graph::dijkstra(St, n * K + 1); std::cout << (ans == 0x3f3f3f3f3f3f3f3f ? -1 : ans) << ' '; if (TIM) { memset(head, 0, sizeof head); cnt = 0; } } return 0; }