【BZOJ 1585】 [Usaco2009 Mar]Earthquake Damage 2 地震傷害 最小割


然后由於是求最少破壞數,還是比較好想得最小割模型,首先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;
}



注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
粤ICP备14056181号  © 2014-2021 ITdaan.com