• 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;
    }
  • 相关阅读:
    NSScanner 的使用
    判断ios设备型号
    图片渲染成蓝色的问题
    UITextView使用体会
    html标签的语义化之搜索引擎优化
    如何用 Canvas绘制图形
    js的几个案例
    js的几种面向对象
    CSS3的几个基本知识点简介
    关于html和CSS的几个基本知识点
  • 原文地址:https://www.cnblogs.com/Hilda/p/2662958.html
Copyright © 2020-2023  润新知