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


    题意就是求最小割…

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

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

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

    证明:

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

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

    综上,最大流=最小割~

    然后看看这道题…哇$nleq 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;
    }
  • 相关阅读:
    常用排序算法--合并排序和快速排序
    常用排序算法--冒泡排序及改进和插入排序时间复杂度分析
    常用数据结构图--拓扑排序
    常用数据结构栈的应用—-表达式求值
    Session原理,生命周期
    jsp内置对象out 和response.getwriter().write()的区别
    div中的div在父容器中水平居中或者垂直居中
    <!DOCTYPE html> 到底是什么意思?
    设置了环境变量,为什么执行javac报找不到javac: 找不到文件
    自动抽取邮件内容
  • 原文地址:https://www.cnblogs.com/yoshinow2001/p/8424431.html
Copyright © 2020-2023  润新知