因为是三元组
<x,y,z>
<script type="math/tex" id="MathJax-Element-3">
</script>
暴力枚举处于x位置的高谷,然后建网络流的图,每次跑dinic取最大流。
枚举位置时直接dfs,上界是高谷总数的一半。
可以证明答案一定在dfs出的结果内。
#include <cstdio>
#include <queue>
#include <cstring>
using namespace std;
int T,n,m,k,kd;
int hi[100],tot,ans;
int map[100][100];
int le[100];
bool in[100];
bool ff[100];
int s,t;
struct edge{
int ro, flow, v, nxt;
}e[2500];
int num;
int cur[100];
int vis[100];
int dis[100];
int head[100];
inline void add_e(int ro,int u,int v)
{
e[num].ro=ro,e[num].v=v,e[num].flow=0,e[num].nxt=head[u],head[u]=num,num++;
e[num].ro=0,e[num].v=u,e[num].flow=0,e[num].nxt=head[v],head[v]=num,num++;
}
inline bool bfs(int s,int t)
{
int i;
memset(vis,0,sizeof(vis));
queue<int> q;
dis[s]=0;vis[s]=1;
q.push(s);
while (!q.empty())
{
int x=q.front();
q.pop();
for (i=head[x];i;i=e[i].nxt)
{
if (!vis[e[i].v]&&e[i].ro>e[i].flow)
{
q.push(e[i].v);
vis[e[i].v]=1;
dis[e[i].v]=dis[x]+1;
}
}
}
return vis[t];
}
inline int dfs(int x,int a)
{
if (x==t||a==0) return a;
int flow=0,f;
for (int& i=cur[x];i;i=e[i].nxt)
{
if (dis[x]+1==dis[e[i].v]&&((f=dfs(e[i].v,min(a,e[i].ro-e[i].flow)))>0))
{
e[i].flow+=f;
e[i^1].flow-=f;
flow+=f;
a-=f;
if (a==0) break;
}
}
return flow;
}
int dinic(int S,int T)
{
int fwf=0;
while (bfs(S,T))
{
for (int i=0;i<=n+n+1;i++) cur[i]=head[i];
fwf+=dfs(s,0x3f3f3f);
}
return fwf;
}
inline int make()
{
int i=0,j=0;
num=2;
s=0,t=n+n+1;
memset(head,0,sizeof(head));
for (i=1;i<=kd;i++) add_e(1,s,le[i]);
for (i=1;i<=n;i++) if (!in[i]) add_e(1,i,i+n);
for (i=1;i<=n;i++) if (in[i]&&!ff[i]) add_e(1,i,t);
for (i=1;i<=kd;i++)
{
for (j=1;j<=n;j++)
{
if (map[le[i]][j]&&!in[j])
add_e(1,le[i],j);
}
}
for (i=1;i<=n;i++)
{
if (!in[i])
{
for (j=1;j<=n;j++)
{
if (in[j]&&!ff[j]&&map[i][j])
add_e(1,i+n,j);
}
}
}
return dinic(s,t);
}
void dfs1(int now,int tot)
{
if (k-now+tot+1<kd) return ;
if (tot==kd) {ans=max(make(),ans);return ;}
if (now>k) return ;
le[++tot]=hi[now];ff[hi[now]]=1;
dfs1(now+1,tot);--tot;ff[hi[now]]=0;
dfs1(now+1,tot);
}
int main()
{
register int i,j,l;
scanf("%d",&T);
for (l=1;l<=T;l++)
{
memset(in,0,sizeof(in));
memset(hi,0,sizeof(hi));
memset(map,0,sizeof(map));
scanf("%d %d %d",&n,&m,&k);
kd=k/2;
int x,y;tot=ans=0;
for (i=1;i<=m;i++)
{
scanf("%d %d",&x,&y);
map[x][y]=map[y][x]=1;
}
for (i=1;i<=k;i++) scanf("%d",&hi[++tot]),in[hi[tot]]=1;;
dfs1(1,0);
printf("%d\n",ans);
}
return 0;
}