然后由于是求最少破坏数,还是比较好想得最小割模型,首先1号节点最为汇点,然后确定源点,因为题目是要求我们将给出的节点和1号节点分开,也就是要求出一条最小割将给出的点和1号节点隔开就好了,所以建立一个源点和所有给出的点连边容量为INF保证它不会被割掉就好了,然后拆点,给出的点一定是可行的所以边权为INF其他的为1,特别注意1号节点边权也是INF或者直接令1的入点为汇点,没了。
#include<cstdio>
#include<cstring>
#include<iostream>
#define Q(a) (a+p)
#define maxn 500020
using namespace std;
int q[maxn],s,t,p,c,n,last[maxn],head[maxn],tot,h[maxn];
bool vvis[maxn];
struct edge{int v,next,w;}e[maxn];
void adde(int a,int b,int c){
e[tot].v=b,e[tot].next=head[a],e[tot].w=c;head[a]=tot++;
e[tot].v=a,e[tot].next=head[b],e[tot].w=0;head[b]=tot++;
}
bool bfs(){
int l=0,r=1;
for(int i=s;i<=2*p;i++)h[i]=-1;
q[l]=h[0]=0;
while(l<r){
int u=q[l++];
for(int v,i=head[u];i!=-1;i=e[i].next){
if(h[v=e[i].v]==-1&&e[i].w){
h[v]=h[u]+1;
q[r++]=v;
}
}
}
return h[t]!=-1;
}
int dfs(int u,int f){
if(u==t)return f;
int used=0,w;
for(int v,i=last[u];i!=-1;i=e[i].next)if(e[i].w&&h[v=e[i].v]==h[u]+1){
w=min(f-used,e[i].w);
last[u]=i;
w=dfs(v,w);
e[i].w-=w,e[i^1].w+=w,used+=w;
if(used==f)return f;
}
if(used==0)h[u]=-1;
return used;
}
int dinic(){
int ans=0;
while(bfs()){
for(int i=s;i<=2*p;i++)last[i]=head[i];
ans+=dfs(s,1e9);
}
return ans;
}
int main(){
scanf("%d%d%d",&p,&c,&n);
t=Q(1);memset(head,-1,sizeof(head));
for(int a,b,i=1;i<=c;i++){
scanf("%d%d",&a,&b);
adde(Q(a),b,1e9),adde(Q(b),a,1e9);
}
for(int a,i=1;i<=n;i++){
scanf("%d",&a);
vvis[a]=true;adde(s,a,1e9);
}
for(int i=1;i<=p;i++)
if(i==1||vvis[i])adde(i,Q(i),1e9);
else adde(i,Q(i),1);
printf("%d",dinic());
return 0;
}