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;

}

你可能感兴趣的:(poj)