状态压缩DP + SPFA
//============================================================================ // Name : hdu4114.cpp // Author : 0222_ // Version : // Copyright : Your copyright notice // Description : Hello World in C++, Ansi-style //============================================================================ #include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <queue> #include <algorithm> #define inf 1000000000 #define N 55 #define K 8 #define M (1 << 8) + 5 #define pause cout << "按任意键继续......", cin >> ch; using namespace std; int T, n, m, k, size; int lt[K], st[K], ha[N], hp[N]; int g[N][N]; int dp[M][M][N]; bool vis[N]; queue<int> q; int init() { int i, j; memset(ha, 0, sizeof(ha)); memset(hp, 0, sizeof(hp)); for (i = 0; i < n; i++) for (j = 0; j < n; j++) g[i][j] = inf; return 1; } int get_min(int &x, int y) { x = min(x, y); return 1; } int main() { int i, j, h, p, u, v, w, cas = 0, tmp; int ch; scanf("%d", &T); while (T--) { scanf("%d%d%d", &n, &m, &k); init(); for (i = 0; i < m; i++) { scanf("%d%d%d", &u, &v, &w); u--, v--; g[u][v] = g[v][u] = min(g[u][v], w); } for (i = 0; i < n; i++) g[i][i] = inf; for (i = 0; i < k; i++) { scanf("%d%d%d", &v, <[i], &st[i]); v--; ha[v] |= (1 << i); scanf("%d", &u); while (u--) { scanf("%d", &v); v--; hp[v] |= (1 << i); } }; for (i = 0; i < (1 << k); i++) { for (j = 0; j < (1 << k); j++) { if (i & j) continue; for (h = 0; h < n; h++) dp[i][j][h] = inf; } } dp[0][0][0] = 0; for (i = 0; i < (1 << k); i++) { for (j = 0; j < (1 << k); j++) { if (i & j) continue; int *dis = dp[i][j]; for (h = 0; h < n; h++) { vis[h] = 1; q.push(h); } while (!q.empty()) { u = q.front(); vis[u] = 0; for (h = 0; h < n; h++) { if (dis[u] + g[u][h] < dis[h]) { dis[h] = dis[u] + g[u][h]; if (vis[h] == 0) vis[h] = 1, q.push(h); } } q.pop(); } for (h = 0; h < n; h++) { get_min(dp[i][(j | hp[h]) & (~i)][h], dp[i][j][h]); tmp = dp[i][j][h]; for (p = 0; p < k; p++) { if (!((i >> p) & 1) && ((ha[h] >> p) & 1)) tmp += ((j >> p) & 1) ? st[p] : lt[p]; } get_min(dp[i | ha[h]][j & ~(i | ha[h])][h], tmp); } } } printf("case #%d: %d\n", ++cas, dp[(1 << k) - 1][0][0]); } return 0; }