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;
    
}

猜你喜欢

转载自blog.csdn.net/guogai13/article/details/83010717