zoukankan      html  css  js  c++  java
  • [BeiJing2006]狼抓兔子

    [BeiJing2006]狼抓兔子

    BZOJhttp://www.lydsy.com/JudgeOnline/problem.php?id=1001
    洛谷https://www.luogu.org/problemnew/show/P4001


    题目描述

    现在小朋友们最喜欢的"喜羊羊与灰太狼",话说灰太狼抓羊不到,但抓兔子还是比较在行的,而且现在的兔子还比较笨,它们只有两个窝,现在你做为狼王,面对下面这样一个网格的地形:
    左上角点为(1,1),右下角点为(N,M)(上图中N=3,M=4).有以下三种类型的道路
    1:(x,y)<>(x+1,y)
    2:(x,y)<
    >(x,y+1)
    3:(x,y)<==>(x+1,y+1)
    道路上的权值表示这条路上最多能够通过的兔子数,道路是无向的. 左上角和右下角为兔子的两个窝,开始时所有的兔子都聚集在左上角(1,1)的窝里,现在它们要跑到右下角(N,M)的窝中去,狼王开始伏击这些兔子.当然为了保险起见,如果一条道路上最多通过的兔子数为K,狼王需要安排同样数量的K只狼,才能完全封锁这条道路,你需要帮助狼王安排一个伏击方案,使得在将兔子一网打尽的前提下,参与的狼的数量要最小。因为狼还要去找喜羊羊麻烦。

    输入格式:

    第一行为N,M.表示网格的大小,N,M均小于等于1000.
    接下来分三部分
    第一部分共N行,每行M-1个数,表示横向道路的权值.
    第二部分共N-1行,每行M个数,表示纵向道路的权值.
    第三部分共N-1行,每行M-1个数,表示斜向道路的权值.

    输出格式:

    输出一个整数,表示参与伏击的狼的最小数量.

    输入样例:

    3 4
    5 6 4
    4 3 1
    7 5 3
    5 6 7 8
    8 7 6 5
    5 5 5
    6 6 6

    输出样例:

    14


    题目意思:删除一些边使得起点和终点不连通,且这些边的边权和最小[专有名词:最小割]
    由于最小割==最大流
    因此(Dinic)跑一遍最大流即可
    注意题目的(<==>)符号,在连边时应连双向边

    建图:
    设点(i,j),则其编号为m*(i-1)+j.
    起点为1号,终点为n*m号.
    将所有(x,y)与(x,y+1),(x+1,y),(x+1,y+1)连接即可.
    
    #define RG register
    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<queue>
    using namespace std;
    const int N=1e6+2;
    inline int read()
    {
    	RG int x=0,w=1;RG char ch=getchar();
    	while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
    	while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
    	return x*w;
    }
    int n,m,s,t,cnt=1,Ans;
    int last[N],dep[N],cur[N];
    struct edge{
    	int to,next,w;
    }e[6*N];
    inline void insert(int u,int v,int w)
    {
    	e[++cnt]=(edge){v,last[u],w};last[u]=cnt;
    	e[++cnt]=(edge){u,last[v],w};last[v]=cnt;//双向边
    }
    queue<int> Q;
    inline bool bfs()
    {
    	while(!Q.empty())Q.pop();
    	memset(dep,0,sizeof(dep));
    	dep[s]=1;
    	Q.push(s);
    	while(!Q.empty())
    	{
    		int now=Q.front();Q.pop();
    		for(int i=last[now];i;i=e[i].next)
    		{
    			int v=e[i].to;
    			if(e[i].w>0&&dep[v]==0)
    			{
    				dep[v]=dep[now]+1;
    				Q.push(v);
    			}
    		}
    	}
    	return dep[t]!=0;
    }
    int dfs(int now,int dist)
    {
    	if(now==t)return dist;
    	for(int& i=cur[now];i;i=e[i].next)
    	{
    		int v=e[i].to;
    		if(dep[v]==dep[now]+1&&e[i].w!=0)
    		{
    			int di=dfs(v,min(dist,e[i].w));
    			if(di>0){e[i].w-=di;e[i^1].w+=di;return di;}
    		}
    	}
    	return 0;
    }
    int main()
    {
        n=read();m=read();
    	for(int i=1;i<=n;i++)
    		for(int j=1;j<m;j++)
    			insert(m*(i-1)+j,m*(i-1)+j+1,read());
    	for(int i=1;i<n;i++)
    		for(int j=1;j<=m;j++)
    			insert(m*(i-1)+j,m*i+j,read());
    	for(int i=1;i<n;i++)
    		for(int j=1;j<m;j++)
    			insert(m*(i-1)+j,m*i+j+1,read());
    	s=1,t=n*m;
    	while(bfs())
    	{
    		for(int i=s;i<=t;i++)cur[i]=last[i];
    		while(int d=dfs(s,1e9))Ans+=d;
    	}
    	printf("%d
    ",Ans);
    	return 0;
    }
    
  • 相关阅读:
    常见自动化场景处理
    等待设置的三种方法
    selenium-浏览器操作
    一个 tomcat 下如何部署多个项目?附详细步骤
    Python篇:测试小白也能懂的常用加密算法解析
    如何高效开展测试用例评审?附用例评审检查清单及用例评审报告模板
    手机大厂必备测试技能-GMS 认证
    Python自动化 让接口数据秒变 python 代码
    Python自动化 谈谈 cookies
    Python自动化 作为代码小白,我是这样成为自动化大神的!
  • 原文地址:https://www.cnblogs.com/sdzwyq/p/8462363.html
Copyright © 2011-2022 走看看