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

题意就是求最小割…

然后我们有这么一个定理(最大流-最小割定理 )

任何一个网络图的最小割中边的容量之和等于图的最大流。

(下面直接简称为最大流和最小割)

证明:

如果最大流>最小割,那把这些割边删去之后依然能找到一条增广路使得源点和汇点联通,和这些边是最小割矛盾。故最大流$\leq$最小割。

而如果最大流<最小割,可是这样通过这些割边还能有更大的流,和最大流矛盾。

综上,最大流=最小割~

然后看看这道题…哇$n\leq 1000$,百万个点百万条边…好吧Dinic其实跑得过…而且还蛮快的…

(我怀疑正解应该是平面图最小割转对偶图最短路?毕竟dinic的理论复杂度好像不太行…)

#include<cstdio>
#define rep(i,a) for(register int i=1;i<=a;++i)
#define debug(x) printf("%s = %d  ",#x,x)
const int N=1000005;
const int M=1000005;
const int INF=(~0u>>1);
struct edge
{
    int to,nxt,w;
    edge(int to=0,int nxt=0,int w=0):to(to),nxt(nxt),w(w){}
}edges[N*10];
int n,m,cnt,st,ed,s,t,ans;
int head[N*10],d[N],q[N];
inline int min(int a,int b){return a<b?a:b;}
inline void addEdge(int u,int v,int w)
{
    edges[++cnt]=edge(v,head[u],w);head[u]=cnt;
    edges[++cnt]=edge(u,head[v],w);head[v]=cnt;
}
#define cur edges[i].to
inline bool bfs()
{
    rep(i,t)d[i]=0;d[s]=1;
    st=ed=0;q[st++]=s;
    while(ed<st)
    {
        int k=q[ed++];
        for(register int i=head[k];i;i=edges[i].nxt)if(edges[i].w&&!d[cur])
        {
            d[cur]=d[k]+1;q[st++]=cur;
            if(cur==t)return 1;
        }
    }
    return 0;
}
inline int dinic(int x,int f)
{
    if(x==t)return f;
    int res=f;
    for(register int i=head[x];i&&res;i=edges[i].nxt)if(edges[i].w&&d[cur]==d[x]+1)
    {
        int k=dinic(cur,min(res,edges[i].w));
        if(!k)d[cur]=0;
        edges[i].w-=k;edges[i^1].w+=k;res-=k;
    }
    return f-res;
}

#undef cur
inline int get_num(int i,int j)
{
    return (i-1)*m+j;
}
int main()
{
    scanf("%d%d",&n,&m);cnt=1;s=get_num(1,1);t=get_num(n,m);
    int x;
    rep(i,n)rep(j,m-1){scanf("%d",&x);addEdge(get_num(i,j),get_num(i,j+1),x);}
    rep(i,n-1)rep(j,m){scanf("%d",&x);addEdge(get_num(i,j),get_num(i+1,j),x);}
    rep(i,n-1)rep(j,m-1){scanf("%d",&x);addEdge(get_num(i,j),get_num(i+1,j+1),x);}
    int flow;
    while(bfs())while((flow=dinic(s,INF)))ans+=flow;
    printf("%d",ans);
    return 0;
}

原文地址:https://www.cnblogs.com/yoooshinow/p/8424431.html

时间: 2024-07-30 03:58:07

[日常摸鱼]bzoj1001狼抓兔子-最大流最小割的相关文章

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

题面: 传送门 思路: 其实就是一道最小割的题目...... 我的写法加了两个优化,常数比较小,所以过掉了 一个是当前弧,一个是若当前点并不能流出去,那么标记dep为-1 听说正解是对偶图最短路?可以找时间学一学...... Code: #include<iostream> #include<cstring> #include<cstdio> #include<algorithm> #define inf 1e9 #define id(i,j) (i-1)*

【建图+最短路】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) 道路上的权值表示这条路上最多能够通过的兔子数,道路是

[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) 道路上的权值表示这条路上最多能够通过的兔子数,道路是无向的. 左上角和右下角

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)

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

bzoj1001 狼抓兔子

这道题 我只会最大流写法 加了当前弧优化就过了 只看代码就oaky了 相信各位大佬都懂的 不过这道题反向弧和反向边可以弄在一起 会快很多 1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 const int maxn=1000005,inf=0x3f3f3f3f; 6 int n,m,sum=1,S,T; 7 long long ans; 8 int

BZOJ1001 狼抓兔子 终于过了!

时间来不及了,先贴代码吧!有时间再写. 好苦逼啊,WA了若干次,还有一次RE,一次TLE. 虽然主要运用的算法和资料都由师兄提供了.还是太弱了,太天真了. 1 #include<cstdio> 2 #include<iostream> 3 #include<queue> 4 #include<cstring> 5 #define maxn 2100009 6 #define rep(i,j,k) for(int i = j; i <= k; i++)

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

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