[BJOI2006][bzoj1001] 狼抓兔子 [最小割]

题面:

传送门

思路:

其实就是一道最小割的题目......

我的写法加了两个优化,常数比较小,所以过掉了

一个是当前弧,一个是若当前点并不能流出去,那么标记dep为-1

听说正解是对偶图最短路?可以找时间学一学......

Code:

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#define inf 1e9
#define id(i,j) (i-1)*m+j
using namespace std;
inline int read(){
    int re=0,flag=1;char ch=getchar();
    while(ch<‘0‘||ch>‘9‘){
        if(ch==‘-‘) flag=-1;
        ch=getchar();
    }
    while(ch>=‘0‘&&ch<=‘9‘) re=(re<<1)+(re<<3)+ch-‘0‘,ch=getchar();
    return re*flag;
}
int n,m,cnt=-1,ans,first[1000010],dep[1000010],cur[1000010];
int q[1000010],head,tail;
struct edge{
    int to,next,cap;
}a[6000010];
inline void add(int u,int v,int cap){
    a[++cnt]=(edge){v,first[u],cap};first[u]=cnt;
    a[++cnt]=(edge){u,first[v],cap};first[v]=cnt;
}
bool bfs(int s,int t){
    int i,u,v;
    head=0,tail=1;q[0]=s;
    for(i=s;i<=t;i++) dep[i]=-1,cur[i]=first[i];
    dep[s]=1;
    while(head<tail){
        u=q[head++];
        for(i=first[u];~i;i=a[i].next){
            v=a[i].to;
            if(~dep[v]||(!a[i].cap)) continue;
            dep[v]=dep[u]+1;
            q[tail++]=v;
        }
    }
    return ~dep[t];
}
int dfs(int u,int t,int limit){
    if(u==t||!limit) return limit;
    int i,v,f,flow=0;
    for(i=cur[u];~i;i=a[i].next){
        v=a[i].to;cur[u]=i;//优化一
        if(dep[v]==dep[u]+1&&a[i].cap>0){
            f=dfs(v,t,min(limit,a[i].cap));
            if(f){
                flow+=f;limit-=f;
                a[i].cap-=f;a[i^1].cap+=f;
                if(!limit) return flow;
            }
            else{
                dep[v]=-1;continue;//优化二
            }
        }
    }
    return flow;
}
void dinic(int s,int t){
    int tmp;
    while(bfs(s,t)){
        while(tmp=dfs(s,t,inf)) ans+=tmp;
    }
}
int main(){
    memset(first,-1,sizeof(first));
    int i,j,t1;
    n=read();m=read();
    for(i=1;i<=n;i++){
        for(j=1;j<m;j++){
            t1=read();
            add(id(i,j),id(i,j+1),t1);
        }
    }
    for(i=1;i<n;i++){
        for(j=1;j<=m;j++){
            t1=read();
            add(id(i,j),id(i+1,j),t1);
        }
    }
    for(i=1;i<n;i++){
        for(j=1;j<m;j++){
            t1=read();
            add(id(i,j),id(i+1,j+1),t1);
        }
    }
    dinic(1,n*m);
    printf("%d",ans);
}

原文地址:https://www.cnblogs.com/dedicatus545/p/8457378.html

时间: 2024-08-13 04:59:18

[BJOI2006][bzoj1001] 狼抓兔子 [最小割]的相关文章

BZOJ 1001 Beijing 2006 狼抓兔子 最小割

题目大意:有一张无向图,描述的是兔子窝的位置和之间的边.现在狼来抓兔子了,兔子慌忙的从(1,1)逃走到(m,n).每条边上都有能通过最多的兔子数量.狼不想让兔子逃走,每在一条边驻守一只狼就可以避免一个兔子通过.问最少多少狼可以让所有兔子都不能逃走. 思路:建图,按题目中的意思是去掉最小的边使得源到汇不连通,显然的最小割. CODE: #include <queue> #include <cstdio> #include <cstring> #include <io

BZOJ 1001: [BeiJing2006]狼抓兔子 最小割

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1001 现在小朋友们最喜欢的"喜羊羊与灰太狼",话说灰太狼抓羊不到,但抓兔子还是比较在行的,而且现在的兔子还比较笨,它们只有两个窝,现在你做为狼王,面对下面这样一个网格的地形: 左上角点为(1,1),右下角点为(N,M)(上图中N=4,M=5).有以下三种类型的道路 1:(x,y)<==>(x+1,y) 2:(x,y)<==>(x,y+1) 3:(x,y)

[BJOI2006] [BZOJ1001] 狼抓兔子

现在小朋友们最喜欢的"喜羊羊与灰太狼",话说灰太狼抓羊不到,但抓兔子还是比较在行的,而且现在的兔子还比较笨,它们只有两个窝,现在你做为狼王,面对下面这样一个网格的地形: 左上角点为(1,1),右下角点为(N,M)(上图中N=4,M=5).有以下三种类型的道路 1:(x,y)<==>(x+1,y) 2:(x,y)<==>(x,y+1) 3:(x,y)<==>(x+1,y+1) 道路上的权值表示这条路上最多能够通过的兔子数,道路是无向的. 左上角和右下角

[日常摸鱼]bzoj1001狼抓兔子-最大流最小割

题意就是求最小割- 然后我们有这么一个定理(最大流-最小割定理 ): 任何一个网络图的最小割中边的容量之和等于图的最大流. (下面直接简称为最大流和最小割) 证明: 如果最大流>最小割,那把这些割边删去之后依然能找到一条增广路使得源点和汇点联通,和这些边是最小割矛盾.故最大流$\leq$最小割. 而如果最大流<最小割,可是这样通过这些割边还能有更大的流,和最大流矛盾. 综上,最大流=最小割~ 然后看看这道题-哇$n\leq 1000$,百万个点百万条边-好吧Dinic其实跑得过-而且还蛮快的-

bzoj 1001 [BeiJing2006]狼抓兔子 最小割+最短路

题面 题目传送门 解法 将最大流转化成最小割,然后跑最短路即可 具体如何见图可以参考下图 尽量用dijkstra 代码 #include <bits/stdc++.h> #define PI pair <int, int> #define mp make_pair #define N 1010 using namespace std; template <typename node> void chkmax(node &x, node y) {x = max(x

BZOJ1001: [BeiJing2006]狼抓兔子 (最小割转最短路)

浅析最大最小定理在信息学竞赛中的应用---周东 ↑方法介绍 对于一个联通的平面图G(满足欧拉公式) 在s和t间新连一条边e; 然后建立一个原图的对偶图G*,G*中每一个点对应原图中每一个面,每一条边对应分割面的每一条边; 那么对偶图G*中,以原图s和t间边e新划分出的面作为起点(s*),最外的面作为终点(t*); 那么从s*到t*的每一条路都是原图G的一个割; 下图来自上方标出百度文库网址的ppt; 然后用堆(优先队列)优化的迪杰斯特拉,复杂度 O((m+n)logn) n为点数,m为边数...

P2030 - 【BJOI2006】狼抓兔子

P2030 - [BJOI2006]狼抓兔子 Description 八中OJ上本题链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1001 现在小朋友们最喜欢的"喜羊羊与灰太狼",话说灰太狼抓羊不到,但抓兔子还是比较在行的,而且现在的兔子还比较笨,它们只有两个窝,现在你做为狼王,面对下面这样一个网格的地形: 左上角点为(1,1),右下角点为(N,M)(上图中N=4,M=5).有以下三种类型的道路 1:(x,y)<==>

【建图+最短路】Bzoj1001 狼抓兔子

Description 现在小朋友们最喜欢的"喜羊羊与灰太狼",话说灰太狼抓羊不到,但抓兔子还是比较在行的,而且现在的兔子还比较笨,它们只有两个窝,现在你做为狼王,面对下面这样一个网格的地形: 左上角点为(1,1),右下角点为(N,M)(上图中N=4,M=5).有以下三种类型的道路 1:(x,y)<==>(x+1,y) 2:(x,y)<==>(x,y+1) 3:(x,y)<==>(x+1,y+1) 道路上的权值表示这条路上最多能够通过的兔子数,道路是

bzoj1001狼抓兔子

这题就一个裸的网络流吧,其实也可以用最短路. 主要就是建边的时候注意一下,其他就没有了. 1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <queue> 5 using namespace std; 6 const int N=1000010; 7 const int inf=1e9+7; 8 struct edge { 9 int v,next,c,f; 1