zoukankan      html  css  js  c++  java
  • 全局最小割 学习总结

    全局最小割的意思是在一个无向图中任取S和T,求最小割的最小值

    还有一种描述是删掉无向图中的边使得其不连通的最小代价

    当然,这种题目可以用分治+最小割来求解

    但是时间复杂度大约在O(n^4)左右

    有一种更好的求解方法可以在O(n^3)的时间复杂度内求解

    做法是这样的:

    首先对于图中任意两点S->T

    要么S和T不在一个集合里时是答案,答案显然是S和T的最小割

    否则S和T在一个集合里,我们可以将S和T缩成一个点,不难证明这样是等效的

    我们模拟这个过程,每次任取S和T跑最小割,时间复杂度大概跟分治+最小割差不多OwO

    但是我们注意到这一步的S和T都是任取的,也就是我们只需要求出一组解就可以了

    这样就有了一种构造算法:

    1、一开始A集合为空,我们任取一点加入A集合中

    2、定义W(A,x)表示A集合所有点到x的边权和

    3、每次寻找W(A,x)最大的点(相同的话任取),加入A集合中并更新其他的W值

    4、最后加入的两个点则分别是S和T,其最小割为最后加入时W(A,T)

    这个过程直接模拟显然是O(n^2)的,加上缩点最多进行O(n)次

    所以总时间复杂度O(n^3),可以用堆优化,但是稠密图跑得很慢很慢

    BZOJ 3345

     
    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<iostream>
    #include<algorithm> 
    using namespace std;
     
    const int maxn=510;
    const int oo=0x7fffffff;
    int n,m,u,v,d;
    int S,T,cut;
    int f[maxn][maxn];
    int w[maxn];
    bool com[maxn],vis[maxn];
     
    void Get_ans(){
        cut=oo;S=T=-1;
        memset(vis,false,sizeof(vis));
        memset(w,0,sizeof(w));
        for(int i=1;i<=n;++i){
            int mx=-oo,tmp;
            for(int j=1;j<=n;++j){
                if(!com[j]&&!vis[j]&&w[j]>mx){
                    mx=w[j];tmp=j;
                }
            }
            if(T==tmp)return;
            S=T;T=tmp;
            cut=mx;vis[tmp]=true;
            for(int j=1;j<=n;++j)if(!com[j]&&!vis[j])w[j]+=f[tmp][j];
        }return;
    }
    int Get_SW(){
        memset(com,false,sizeof(com));
        int ans=oo;
        for(int i=1;i<n;++i){
            Get_ans();
            ans=min(ans,cut);
            if(ans==0)return 0;
            com[T]=true;
            for(int j=1;j<=n;++j){
                if(!com[j]){f[S][j]+=f[T][j];f[j][S]+=f[j][T];}
            }
        }return ans;
    }
     
    int main(){
        scanf("%d%d",&n,&m);
        memset(f,0,sizeof(f));
        for(int i=1;i<=m;++i){
            scanf("%d%d%d",&u,&v,&d);
            f[u][v]+=d;f[v][u]+=d;
        }
        printf("%d
    ",Get_SW());
        return 0;
    }
    
    

    hdu 3691

    注意到这里的S是给定的

    但是不难发现这并没有什么卵用,答案还是全局最小割

    因为设最后全局最小割中一定有一个T跟S不属于一个集合OwO

    又因为是全局最小割,所以这组S->T的最小割就是全局最小割

    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    
    typedef long long LL;
    const int maxn=310;
    const LL oo=1LL<<60;
    int n,m,k;
    int u,v,w;
    int S,T;
    LL ans,cut;
    LL f[maxn][maxn];
    LL W[maxn];
    bool com[maxn],vis[maxn];
    
    void read(int &num){
        num=0;char ch=getchar();
        while(ch<'!')ch=getchar();
        while(ch>='0'&&ch<='9')num=num*10+ch-'0',ch=getchar();
    }
    void Get_ans(){
        cut=oo;S=T=-1;
        memset(vis,false,sizeof(vis));
        memset(W,0,sizeof(W));
        for(int i=1;i<=n;++i){
            LL mx=-oo;int tmp;
            for(int j=1;j<=n;++j){
                if(!com[j]&&!vis[j]&&W[j]>mx){mx=W[j];tmp=j;}
            }
            if(T==tmp)return;
            S=T;T=tmp;
            cut=mx;vis[tmp]=true;
            for(int j=1;j<=n;++j){
                if(!com[j]&&!vis[j]){W[j]+=f[tmp][j];}
            }
        }return;
    }
    LL Get_SW(){
        ans=oo;memset(com,0,sizeof(com));
        for(int i=1;i<n;++i){
            Get_ans();
            ans=min(ans,cut);
            if(ans==0)return ans;
            com[T]=true;
            for(int j=1;j<=n;++j){
                if(!com[j]){f[S][j]+=f[T][j];f[j][S]+=f[j][T];}
            }
        }return ans;
    }
    
    int main(){
        while(scanf("%d%d%d",&n,&m,&k)==3){
            if(!n&&!m&&!k)break;
            memset(f,0,sizeof(f));
            for(int i=1;i<=m;++i){
                read(u);read(v);read(w);
                f[u][v]+=w;f[v][u]+=w;
            }
            printf("%d
    ",Get_SW());
        }return 0;
    }
    

      

  • 相关阅读:
    Entity Framework Core 2.0 新特性
    asp.net core部署时自定义监听端口,提高部署的灵活性
    asp.net core使用jexus部署在linux无法正确 获取远程ip的解决办法
    使用xshell连接服务器,数字键盘无法使用解决办法
    使用Jexus 5.8.2在Centos下部署运行Asp.net core
    【DevOps】DevOps成功的八大炫酷工具
    【Network】Calico, Flannel, Weave and Docker Overlay Network 各种网络模型之间的区别
    【Network】UDP 大包怎么发? MTU怎么设置?
    【Network】高性能 UDP 应该怎么做?
    【Network】golang 容器项目 flannel/UDP相关资料
  • 原文地址:https://www.cnblogs.com/joyouth/p/5648681.html
Copyright © 2011-2022 走看看