状态压缩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;
}