题意:给出若干个不能被割的点,问:这若干个给出的点均不与1号点相连的最小代价是割掉几个其它点。
1.由于每个点只能被割一次,或是不能被割,所以首先将每个点拆为入点和出点,对于能被割的点连流量为1的边,对于不能被割的点连流量为inf的边。
2.对于若干个不能被割掉的点均需满足,所以从源点向不能被割掉的点连流量为inf的边。
3.对于相邻的两个点之间,连流量为inf的边,表示路径不能被割掉,只有点才能被割掉。
#include <bits/stdc++.h>
using namespace std;
const int N=3e3+5,M=2e4+5;
int n,m,p,u,v,s,t,inf=1e9;
int dep[N*2];
bool pd[N];
int cnt=1,head[N*2];
struct edge{int next,to,w;}e[M*4+N*4];
inline void add(int u,int v,int w)
{
cnt++;
e[cnt].next=head[u];
e[cnt].to=v;
e[cnt].w=w;
head[u]=cnt;
}
inline void insert(int u,int v,int w)
{
add(u,v,w); add(v,u,0);
}
queue<int>q;
inline bool bfs()
{
memset(dep,-1,sizeof(dep));
dep[s]=0;
q.push(s);
while (q.size())
{
int u=q.front(); q.pop();
for (register int i=head[u]; i; i=e[i].next)
if (e[i].w && dep[e[i].to]==-1)
{
dep[e[i].to]=dep[u]+1;
q.push(e[i].to);
}
}
if (dep[t]==-1) return false;
return true;
}
int dfs(int u,int flow)
{
if (u==t) return flow;
int remain=flow;
for (register int i=head[u]; i; i=e[i].next)
if (e[i].w && dep[u]+1==dep[e[i].to])
{
int k=dfs(e[i].to,min(remain,e[i].w));
if (!k) {dep[e[i].to]=-1; continue;}
remain-=k; e[i].w-=k; e[i^1].w+=k;
if (!remain) break;
}
return flow-remain;
}
inline int dinic()
{
int ans=0;
while (bfs()) ans+=dfs(s,inf);
return ans;
}
int main(){
scanf("%d%d%d",&n,&m,&p);
s=0; t=1;
for (register int i=1; i<=m; ++i)
{
scanf("%d%d",&u,&v);
insert(u+n,v,inf);
insert(v+n,u,inf);
}
for (register int i=1; i<=p; ++i)
{
scanf("%d",&u);
pd[u]=true;
}
for (register int i=1; i<=n; ++i)
if (pd[i]) insert(s,i,inf),insert(i,i+n,inf);
else insert(i,i+n,1);
printf("%d\n",dinic());
return 0;
}