bzoj1001 最小割

題目大意:有n*m個網格點,座標爲(i,j)的點與(i+1,j),(i,j+1),(i+1,j+1zu)間有權值w的無向邊,表示該邊可通過兔子  的最大數量,左上和右下分別爲兔子起點和終點。一頭狼阻只能擋一隻兔子,求要阻擋兔子到達終點的最小狼數量。

思路:最小割。。。。注意所開數組的大小,很容易mle和re。

 

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<queue>
using namespace std;
queue<int>q;
int n,m,dp[1000010];
int p[12000010],nex[12000010],head[1000010],c[12000010],e;
void add(int a,int b,int w){
	  p[e]=b;
	  nex[e]=head[a];
	  head[a]=e;
	  c[e++]=w;
}
int id(int x,int y){
     return x*m+y;
}
int mi(long long a,long long b){
     if(a>b) return b;
     else return a;
}
int bfs(int s,int t){
	  int u,v,i;
	  for(i=0;i<=1000005;i++) dp[i]=1e9;
	  dp[s]=0;
	  for(q.push(s);!q.empty();q.pop()){
	        u=q.front();
	        for(i=head[u];i;i=nex[i]){
	              v=p[i];
	              if(dp[v]>dp[u]+1&&c[i]){
	              	dp[v]=dp[u]+1;
	              	q.push(v);
	              }
	        }
	  }
	  return dp[t]!=1e9;
}
long long dfs(int u,long long flow){
	 if(u==id(n-1,m-1)||flow==0) return flow;
	 long long i,v,sum=0,f;
	 for(i=head[u];i;i=nex[i]){
	       v=p[i];
	       if(dp[v]==dp[u]+1){
	       	 f=dfs(v,mi(flow-sum,c[i]));
	       	 c[i]-=f;
	       	 c[i^1]+=f;
	       	 sum+=f;
	       }
	       if(sum==flow) break;
	 }
	 if(sum==0) dp[u]=1e9;
	 return sum;
}
	  
int main(){
	int i,j,k;
//	freopen("in.txt","r",stdin);
	scanf("%d%d",&n,&m);
	e=2;
	for(i=0;i<n;i++){
		for(j=0;j<m-1;j++){
	         scanf("%d",&k);
	         int x=id(i,j),y=id(i,j+1);
	         add(x,y,k);
	         add(y,x,0);
	         add(y,x,k);
	         add(x,y,0);
		}
	}
	for(i=0;i<n-1;i++){
	     for(j=0;j<m;j++){
	    	scanf("%d",&k);
	        int x=id(i,j),y=id(i+1,j);
	        add(x,y,k);
	        add(y,x,0);
	        add(y,x,k);
	        add(x,y,0);
	     }
	}
	for(i=0;i<n-1;i++){
	     for(j=0;j<m-1;j++){
	    	scanf("%d",&k);
	        int x=id(i,j),y=id(i+1,j+1);
	        add(x,y,k);
	        add(y,x,0);
	        add(y,x,k);
	        add(x,y,0);
	     }
	}
      long long ans=0;
      while(bfs(0,id(n-1,m-1))) ans+=dfs(0,1e18);
      printf("%lld\n",ans);
      return 0;
    
}

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章