zoukankan      html  css  js  c++  java
  • P2598 [ZJOI2009]狼和羊的故事

    既可以是一眼题又可以是有些东西的题

    一眼就可以看出来,要用最小割把狼和羊分开,那 (S) 向狼连 (inf),羊向 (T)(inf),每个点向周围连 1,考虑割掉的边是栅栏

    之所以说它有些东西,是应为它可以表示成数学形式,考虑将狼划分成 0 集合,将羊划分成 1 集合,没有归属的点随便

    如果两个点不在同一个集合,那么它需要栅栏分开,就是每个点向周围连 1 的边,由此可知,0 的归属就不需要讨论了

    #include<bits/stdc++.h>
    using namespace std;
    #define rg register
    inline int read(){
    	rg char ch=getchar();
    	rg int x=0,f=0;
    	while(!isdigit(ch)) f|=(ch=='-'),ch=getchar();
    	while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
    	return f?-x:x;
    }
    int head[100010],ver[200010],flow[200010],nxt[200010],tot=1,hh[100010];
    int mp[110][110];
    int dis[100010],ans;
    int dx[]={0,0,1,-1},dy[]={1,-1,0,0};
    int n,m,s,t;
    inline void add(int x,int y,int f){
    	ver[++tot]=y;
    	flow[tot]=f;
    	nxt[tot]=head[x];
    	head[x]=tot;
    }
    inline int get(int i,int j){
    	return (i-1)*m+j;
    }
    int bfs(){
    	queue<int> q;
    	q.push(s);
    	for(int i=s;i<=t;++i) hh[i]=head[i];
    	memset(dis,0,sizeof dis);
    	dis[s]=1;
    	while(!q.empty()){
    		int x=q.front();q.pop();
    		for(int y,i=head[x];i;i=nxt[i]){
    			y=ver[i];
    			if(!dis[y]&&flow[i]){
    				dis[y]=dis[x]+1;
    				q.push(y);
    			}
    		}
    	}
    	return dis[t]?true:false;
    }
    int dfs(int x,int f){
    	if(x==t||!f) return f;
    	int used=0;
    	for(int y,w,&i=hh[x];i;i=nxt[i]){
    		y=ver[i];
    		if(dis[y]==dis[x]+1&&flow[i]){
    			w=dfs(y,min(f-used,flow[i]));
    			if(w){
    				flow[i]-=w;
    				flow[i^1]+=w;
    				used+=w;
    				if(used==f) return f;
    			}
    		}
    	}
    	if(!used) dis[x]=0;
    	return used;
    }
    void dinic(){
    	while(bfs()) ans+=dfs(s,99999999);
    }
    int main(){
    	n=read(),m=read();
    	for(int i=1;i<=n;++i)
    		for(int j=1;j<=m;++j)
    			mp[i][j]=read();
    	s=0,t=n*m+1;
    	for(int i=1;i<=n;++i){
    		for(int j=1;j<=m;++j){
    			if(mp[i][j]!=1){
    				for(int k=0;k<4;++k){
    					int xl=j+dx[k],yl=i+dy[k];
    					if(xl<1||yl<1||xl>m||yl>n) continue;
    					add(get(i,j),get(yl,xl),1);
    					add(get(yl,xl),get(i,j),0);
    				}
    				if(mp[i][j]==2){
    					add(s,get(i,j),99999999);
    					add(get(i,j),s,0);
    				}
    			}else{
    				add(get(i,j),t,99999999);
    				add(t,get(i,j),0);
    			}
    		}
    	}
    	dinic();
    	cout<<ans<<endl;
    	return 0;
    }
    
  • 相关阅读:
    软件工程课堂二
    大二下学期第三周总结
    大二第二个学期的自我介绍
    如何将非ARC的项目转换成ARC
    UIScrollView
    关于nil和 null和NSNull的区别及相关问题
    提高iOS开发效率的第三方框架等--不断更新中。。。
    iOS中常见的设计模式(MVC/单例/委托/观察者)
    TCP/IP、Http、Socket的区别
    iOS使用AVFoundation实现二维码扫描
  • 原文地址:https://www.cnblogs.com/XiaoVsun/p/13110235.html
Copyright © 2011-2022 走看看