思路:
观察这个
k
≤
6
k\leq6
k≤6,我们是应该想到状态压缩的。准确的说往状压
d
p
dp
dp考虑。
我们定义
d
p
[
i
]
[
j
]
dp[i][j]
dp[i][j]:从起点走到
i
i
i,可带人的状态为
j
j
j。
题目要求了最短路,那么我们选择
b
f
s
bfs
bfs一层一层去扩展,是可以保证最短路的。
跑完之后我们做个简单的背包统计一下最多可以带的人即可。
code:
#define D(x) cout << "BUG: " << (x) << '\n';
#define DD(x, y) cout << "BUG: " << (x) << " " << (y) << '\n';
#define rep(i, x, y) for(int i = (x); i <= (y); i++)
#define per(i, x, y) for(int i = (x); i >= (y); i--)
#define INF 0x3f3f3f3f3f3f3f3fll
#define inf 0x3f3f3f3f
#define sqr(x) ((x) * (x))
#define all(x) (x).begin(), (x).end()
#define pb push_back
#define fi first
#define se second
typedef unsigned long long ULL;
typedef pair<int, int> pii;
template <typename T> void inline read(T& x) {
T f = 1; x = 0; char s = getchar();
while (s < '0' || s > '9') { if (s == '-') f = -1; s = getchar(); }
while (s <= '9' && s >= '0') x = x * 10 + (s ^ 48), s = getchar();
x *= f;
}
//----------------------------------------------------------------------------------------//
const int N = 1e4 + 10, M = N * 2, mod = 998244353;
vector<int> G[N];
bool vis[N];
int n, m, f, h[N], k, p[7];
int dp[N][1 << 7];
//dp[i][j]:从1出发到i带的人状态为j
signed main() {
#ifdef JANGYI
freopen("input.in", "r", stdin);
freopen("out.out", "w", stdout);
#endif
int T; read(T);
while(T--) {
read(n), read(m);
rep(i, 0, n) G[i].clear(), vis[i] = 0;
rep(i, 0, n) memset(dp[i], 0, sizeof dp[i]);
rep(i, 1, m) {
int u, v;
read(u), read(v);
G[u].pb(v), G[v].pb(u);
}
read(f); rep(i, 1, f) read(h[i]);
read(k); rep(i, 1, k) read(p[i]);
vector<pii> q; q.pb({1, 0});
dp[1][0] = 1;
while(q.size()) {
//防止同一层之间的点互相到达
for(auto t : q) vis[t.fi] = 1;
vector<pii> nex;
for(auto t : q) {
for(auto u : G[t.fi]) {
int state = t.se;
for(int i = 1; i <= k; i++)
if(u == h[p[i]]) state |= (1 << i - 1);
if(!dp[u][state] && !vis[u]) {
nex.pb({u, state});
dp[u][state] = 1;
}
}
}
q = nex;
}
rep(i, 1, k) h[p[i]] = 0;
bitset<64> now, pre;
pre[0] = 1;
for(int i = 1; i <= f; i++) {
if(!h[i]) continue;
now = pre;
int u = h[i];
for(int x = 0; x < 64; x++)
for(int y = 0; y < 64; y++)
if(dp[u][y]) now[y | x] = now[y | x] | pre[x];
pre = now;
}
int ans = 0;
for(int i = 0; i < 64; i++)
if(now[i]) ans = max(ans, __builtin_popcount(i));
printf("%d\n", k - ans);
}
return 0;
}