zoukankan      html  css  js  c++  java
  • POJ 2914 Minimum Cut【最小割】

    Description

    Given an undirected graph, in which two vertices can be connected by multiple edges, what is the size of the minimum cut of the graph? i.e. how many edges must be removed at least to disconnect the graph into two subgraphs?

    Input

    Input contains multiple test cases. Each test case starts with two integers N and M (2 ≤ N ≤ 500, 0 ≤ M ≤ N × (N − 1) ⁄ 2) in one line, where N is the number of vertices. Following are M lines, each line contains M integersAB and C (0 ≤ AB < NA ≠ BC > 0), meaning that there C edges connecting vertices A and B.

    Output

    There is only one line for each test case, which contains the size of the minimum cut of the graph. If the graph is disconnected, print 0.

    Sample Input

    3 3
    0 1 1
    1 2 1
    2 0 1
    4 3
    0 1 1
    1 2 1
    2 3 1
    8 14
    0 1 1
    0 2 1
    0 3 1
    1 2 1
    1 3 1
    2 3 1
    4 5 1
    4 6 1
    4 7 1
    5 6 1
    5 7 1
    6 7 1
    4 0 1
    7 3 1

    Sample Output

    2
    1
    2

    反思:最小割算法我很久没有想明白,智商很低吧...相信自己慢慢会理解的;
    一个值得看的资料链接:http://www.cnblogs.com/ylfdrib/archive/2010/08/17/1801784.html
    看着顺眼的代码:
    View Code
    #include <iostream>
    #include <stdio.h>
    #include <string.h>
    using namespace std;
    #define N 505
    #define inf 1000000000
    int n, m;
    int g[N][N];  //保存原图 
    int dist[N], node[N];  //dist[]保存一个积累量, node[]保存顶点 
    bool used[N];
    int mincut()
    {
        int i, j, k, pre, maxj, ans = inf;
        for(i = 0; i < n; i++)
            node[i] = i;    //保存顶点,固定顶点为0
        while(n > 1)
        {
            memset(used,0,sizeof(used));
            maxj = 1;
            used[node[0]] = 1;
            for(i = 1; i < n; i++)
            {
                dist[node[i]] = g[node[0]][node[i]]; //初始化距离数组dist[]
                if(dist[node[i]] > dist[node[maxj]])   //寻找最大距离——求最大生成树
                    maxj = i;
            }
            pre = 0;    //求最大生成树,并进行最小割操作。
            for(i = 1; i < n; i++)
            {
                if(i == n-1)
                {        //只剩最后一个没加入集合的点,更新最小割
                    ans = min(ans,dist[node[maxj]]);
                    for(k = 0; k < n; k++) //合并最后一个点以及推出它的集合中的点
                    g[node[k]][node[pre]] = g[node[pre]][node[k]] += g[node[k]][node[maxj]];
                    node[maxj] = node[--n];//缩点后的图
                }
                used[node[maxj]] = 1;
                pre = maxj;
                maxj = -1;
                for(j = 1; j < n; j++)
                    if(!used[node[j]])
                    {    //将上次求的maxj加入集合,合并与它相邻的边到割集
                        dist[node[j]] += g[node[pre]][node[j]];//dist[]保存的是一个积累量。
                        if(maxj == -1 || dist[node[maxj]] < dist[node[j]])
                            maxj = j;
                    }
            }
        }
         return ans;
    }
    int main()
    {
        while(scanf("%d %d",&n,&m) != -1)
        {
            memset(g,0,sizeof(g));
            while(m--)
            {
                int a, b, c;
                scanf("%d %d %d",&a,&b,&c);
                g[a][b] += c;
                g[b][a] += c;
            }
            printf("%d\n",mincut());
        }
     return 0;
    }
  • 相关阅读:
    【JAVASCRIPT】call和apply的用法以及区别
    web开发中的支付宝支付和微信支付
    【input】标签去除默认样式
    npm run build后如何打开index.html跑起项目
    Sass的混合-@mixin,@include
    ios h5 长按时出现黑色透明遮罩
    ios h5 长按放大镜效果关闭
    vue.$nextTick 解决了哪些问题
    原生JS代码封装(将字符串转换为日期 2019.08.24 )
    原生JS代码封装(获取年月日时分秒 )
  • 原文地址:https://www.cnblogs.com/Hilda/p/2662958.html
Copyright © 2011-2022 走看看