• POJ 2914 Minimum Cut (全局最小割)


    【题目链接】 http://poj.org/problem?id=2914

    【题目大意】

      求出一个最小边割集,使得图不连通

    【题解】

      利用stoerwagner算法直接求出全局最小割,即答案。

    【代码(递归)】

    #include <cstdio>
    #include <algorithm>
    #include <cstring> 
    using namespace std;
    const int INF=0x3f3f3f3f;
    const int MAX_N=510;
    int v[MAX_N],w[MAX_N],c[MAX_N],g[MAX_N][MAX_N],S,T,now,N,M,x,y,z;
    void search(){
        int i,j,k,t;
        for(i=0;i<N;i++)v[i]=w[i]=0;
        for(S=T=-1,i=0;i<N;i++){
            for(k=-INF,j=0;j<N;j++)if(!c[j]&&!v[j]&&w[j]>k)k=w[t=j];
            if(T==t)return;
            S=T,T=t,now=k,v[t]=1;
            for(j=0;j<N;j++)if(!c[j]&&!v[j])w[j]+=g[t][j];
        }
    }
    int stoerwagner(){
        int i,j,ans=INF;
        for(i=0;i<N;i++)c[i]=0;
        for(i=0;i<N-1;i++){
            search();
            if(now<ans)ans=now;
            if(ans==0)return 0;
            for(c[T]=1,j=0;j<N;j++)if(!c[j])g[S][j]+=g[T][j],g[j][S]+=g[j][T];
        }return ans;
    }
    void init(){
        memset(g,0,sizeof(g));
        while(M--)scanf("%d%d%d",&x,&y,&z),g[x][y]+=z,g[y][x]+=z;
    }
    void solve(){
        printf("%d
    ",stoerwagner());
    }
    int main(){
        while(~scanf("%d%d",&N,&M)){
            init();
            solve();
        }return 0;
    }

    【代码(非递归)】

    #include <cstdio>
    #include <algorithm>
    #include <cstring> 
    using namespace std;
    const int INF=0x3f3f3f3f;
    const int MAX_N=510;
    int G[MAX_N][MAX_N],v[MAX_N],f[MAX_N],N,M,vis[MAX_N];
    int Stoer_Wagner(){
        int ret=INF;
        for(int i=1;i<=N;i++)v[i]=i;
        while(N>1){
            int k,lst=v[1];
            memset(vis,0,sizeof(vis));
            memset(f,0,sizeof(f));
            vis[v[1]]=1;
            for(int i=2;i<=N;i++){
                k=1;
                for(int j=2;j<=N;j++)if(!vis[v[j]]&&(f[v[j]]+=G[lst][v[j]])>f[v[k]])k=j;
                vis[v[k]]=1;
                if(i<N)lst=v[k];
            }ret=min(ret,f[v[k]]);
            for(int j=1;j<=N;j++)G[v[j]][lst]=G[lst][v[j]]=G[lst][v[j]]+G[v[k]][v[j]];
            v[k]=v[N--];
        }return ret;
    }
    void init(){
        memset(G,0,sizeof(G));
    	for(int i=1;i<=M;i++){
            int x,y,z;
            scanf("%d%d%d",&x,&y,&z);
            ++x;++y;
            G[x][y]+=z;G[y][x]+=z;
        }
    }
    void solve(){printf("%d
    ",Stoer_Wagner());}
    int main(){
        while(~scanf("%d%d",&N,&M)){
            init();
            solve();
        }return 0;
    }
  • 相关阅读:
    android学习第一天
    定力
    C++ 虚基类表指针字节对齐
    c++内存对齐 转载
    #Pragma Pack(n)与内存分配
    c++ data语意学
    point类型·
    对象内存 (扩展 Data Structure Alignment)
    reinterpret_cast and const_cast
    static_cast AND dynamic_cast
  • 原文地址:https://www.cnblogs.com/forever97/p/poj2914.html
Copyright © 2020-2023  润新知