• POJ 2914


    无向图全局最小割算法

    求 G=(V, E)中任意 s-t 最小割的算法: 
    定义w(A, x) = ∑w(v[i], x),v[i]  A ∈  
    定义 Ax 为在x 前加入 A 的所有点的集合(不包括 x)  
    1. 令集合 A={a},a为 V中任意点  
    2. 选取 V - A中的 w(A, x)最大的点 x加入集合 A  
    3. 若|A|=|V|,结束 
    令倒数第二个加入 A的点为 s,最后一个加入 A的点为 t,则s-t 最小割为 w(At, t)

    即简单来说,就是每次从0点开始,进行一种类似于最大生成树的操作,唯一与最大生成树的区别就是在选择把哪个点加进来的时候,不是根据连到它的边的长度,而是根据它到树的所有边的长度和。然后记录最后两个进树的点合并(缩点),并用这两点间的割来更新最小值。然后不断重复此操作(生成树、缩点、最小值),直到所有点都缩为1点。

    该题是模板题:

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4 #include <algorithm>
     5 using namespace std;
     6 
     7 const int MAXN=510;
     8 const int inf=100000000;
     9 int map[MAXN][MAXN];
    10 int wan[MAXN],combine[MAXN],vis[MAXN];
    11 int n,m;
    12 int S,T,mincut;
    13 
    14 void scut(){
    15     S=T=-1;
    16     int p,Max;
    17     memset(wan,0,sizeof(wan));
    18     memset(vis,0,sizeof(vis));
    19     for(int i=0;i<n;i++){
    20         Max=-inf;
    21         for(int j=0;j<n;j++){
    22             if(!combine[j]&&!vis[j]&&wan[j]>Max){
    23                 p=j; Max=wan[j];
    24             }
    25         }
    26         if(p==T) return ;
    27         S=T; T=p;
    28         vis[T]=1;
    29         for(int j=0;j<n;j++){
    30             if(!combine[j]&&!vis[j]){
    31                 wan[j]+=map[T][j];
    32             }
    33         }
    34     }
    35 }
    36 
    37 void slove(){
    38     memset(combine,0,sizeof(combine));
    39     mincut=inf;
    40     for(int i=0;i<n-1;i++){
    41         scut();
    42         if(mincut>wan[T]) mincut=wan[T];
    43         if(mincut==0) return;
    44         combine[T]=1;
    45         for(int j=0;j<n;j++){
    46             if(!combine[j]){
    47                 map[S][j]+=map[T][j];
    48                 map[j][S]+=map[j][T];
    49             }
    50         }
    51     }
    52 }
    53 
    54 int main(){
    55     int u,v,w;
    56     while(scanf("%d%d",&n,&m)!=EOF){
    57         memset(map,0,sizeof(map));
    58         for(int i=1;i<=m;i++){
    59             scanf("%d%d%d",&u,&v,&w);
    60             map[u][v]+=w;
    61             map[v][u]+=w;
    62         }
    63         slove();
    64         printf("%d
    ",mincut);
    65     }
    66     return 0;
    67 }
    View Code
  • 相关阅读:
    [转载]如何让企业网站发挥出应用的功能?
    [转载]创业流程
    velocity foreach跳出循环
    【转】cgi技术
    webx3 日志系统级别问题
    ibatis主键自增用法
    【转】java内部类总结
    java初始化顺序
    一点一点学习Ubuntu
    jboss 的端口修改
  • 原文地址:https://www.cnblogs.com/jie-dcai/p/3858816.html
Copyright © 2020-2023  润新知