/**
题目:hdu6149 Valley Numer II
链接:http://acm.hdu.edu.cn/showproblem.php?pid=6149
题意:
众所周知,度度熊非常喜欢图。
为了形成山谷,首先要将一个图的顶点标记为高点或者低点。
标记完成后如果一个顶点三元组<X, Y, Z>中,
X和Y之间有边,Y与Z之间也有边,同时X和Z是高点,Y是低点,那么它们就构成一个valley。
度度熊想知道一个无向图中最多可以构成多少个valley,一个顶点最多只能出现在一个valley中。
● 1≤T≤20
● 1≤N≤30
● 1≤M≤N*(N-1)/2
● 0≤K≤min(N,15)
● 1≤Xi, Yi≤N, Xi!=Yi
● 1≤Vi≤N
思路:由于k最大是15,所以可以分组背包+状态压缩 因为每两个高点和一个低点才能构成一个三元组,k最大15,所以最多7个三元组; 所有的低点作为分组条件。
每一组存入可以和该低点构成三元组的pair<x,z>,用s表示状态; dp[i][s]表示放入i体积,高点状态为s可以获得的最多三元组; dp[i][s] = max(dp[i][s],dp[i-1][s-s1]+1) (s&(s1)==0) ps:自己老是在这个地方搞错,dp[7][i]这里的第一维要开到8以上!!! */
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <set>
#include <iostream>
#include <cmath>
#include <vector>
#include <map>
using namespace std;
typedef long long LL;
#define ms(x,y) memset(x,y,sizeof x)
typedef pair<int, int> P;
const int inf = 0x3f3f3f3f;
const int mod = 1e9 + ;
const int N =;
int dp[][<<];
vector<int> v[];
int f[][];
int gao[], pos[];
vector<int> g;
int main()
{
int T;
int n, m, k;
cin>>T;
while(T--)
{
scanf("%d%d%d",&n,&m,&k);
ms(f,);
int x, y;
for(int i = ; i <= m; i++){
scanf("%d%d",&x,&y);
f[x][y] = ;
f[y][x] = ;
}
ms(gao,);
g.clear();
for(int i = ; i <= k; i++){
scanf("%d",&x);
pos[x] = i-;
g.push_back(x);
gao[x] = ;
}
for(int i = ; i<= n; i++) v[i].clear();
for(int i = ; i <= n; i++){
if(gao[i]==){
for(int j = ; j<g.size();j++){
for(int z = j+; z <g.size(); z++){
if(f[i][g[j]]&&f[i][g[z]]){
v[i].push_back((<<pos[g[j]])|(<<pos[g[z]]));
}
}
}
}
}
memset(dp, -inf, sizeof dp);
dp[][] = ;
int len = <<k;
for(int i = ; i <= n; i++){
if(gao[i]||(int)v[i].size()==) continue;
for(int j = ; j >= ; j--){
for(int x = ; x < v[i].size(); x++){
for(int y = ; y < len; y++){
if((y&v[i][x])==v[i][x]){
dp[j][y] = max(dp[j][y],dp[j-][y-v[i][x]]+);
}
}
}
}
}
int mas = ;
for(int i = ; i <= ; i++){
for(int j = ; j < len; j++){
mas = max(mas,dp[i][j]);
}
}
printf("%d\n",mas);
}
return ;
}