POJ2914 Minimum Cut 【全局最小割】(Stoer_Wagner)

Minimum Cut

Time Limit: 10000MS   Memory Limit: 65536K
Total Submissions: 7610   Accepted: 3203
Case Time Limit: 5000MS

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

Source

Baidu Star 2006 Semifinal

Wang, Ying (Originator)

Chen, Shixi (Test cases)

题意:求裸的最小割。

题解:过程有点像求“最大生成树”,每次找到将最后的点(即割点值最小的点)隔离出去的最小割大小nowcut,然后用nowcut更新结果mincut,然后将最后两个点合并,方式是将最后一个点合并到倒数第二个点,边也都合并过去,就这样循环下去直到只剩下一个顶点,此时mincut即为所求。

#include <stdio.h>
#include <string.h>
#define inf 0x7fffffff
#define maxn 502

int map[maxn][maxn], W[maxn], hash[maxn];
bool vis[maxn];

void getMap(int n, int m)
{
    int i, u, v, c;
    memset(map, 0, sizeof(map));
    for(i = 0; i < m; ++i){
        scanf("%d%d%d", &u, &v, &c);
        map[u][v] += c; map[v][u] += c;
    }
}

int Stoer_Wagner(int n)
{
    int minCut = inf, nowCut, now, pre, i, j;
    for(i = 0; i < n; ++i) hash[i] = i;
    while(n > 1){
        nowCut = -1; now = 1; vis[hash[0]] = 1; pre = 0;
        for(i = 1; i < n; ++i){
            W[hash[i]] = map[hash[0]][hash[i]];
            vis[hash[i]] = 0;
            if(W[hash[i]] > nowCut){
                nowCut = W[hash[i]]; now = i;
            }
        }
        for(j = 1; j < n; ++j){
            vis[hash[now]] = 1;
            if(j == n - 1){
                if(nowCut < minCut) minCut = nowCut;
                for(i = 0; i < n; ++i){
                    map[hash[pre]][hash[i]] += map[hash[now]][hash[i]];
                    map[hash[i]][hash[pre]] += map[hash[now]][hash[i]];
                }
                hash[now] = hash[--n];
                break;
            }
            pre = now; nowCut = -1;
            for(i = 1; i < n; ++i){
                if(!vis[hash[i]]){
                    W[hash[i]] += map[hash[pre]][hash[i]];
                    if(W[hash[i]] > nowCut){
                        nowCut = W[hash[i]]; now = i;
                    }
                }
            }
        }
    }
    return minCut;
}

void solve(int n)
{
    printf("%d\n", Stoer_Wagner(n));
}

int main()
{
    freopen("stdin.txt", "r", stdin);
    int n, m;
    while(scanf("%d%d", &n, &m) == 2){
        getMap(n, m);
        solve(n);
    }
    return 0;
}
时间: 2024-11-05 04:00:26

POJ2914 Minimum Cut 【全局最小割】(Stoer_Wagner)的相关文章

POJ 2914 - Minimum Cut - 全局最小割,Stoer-Wagner算法

题目大意:给定一个N个点.M条边的无向带权图,边的权值均为正整数.若要使它变成非连通图,需要移除的边总权值最小是多少? N≤500,图中不存在自环,但可能有重边(这里题意没交代清楚). Stoer-Wagner算法裸题.英文维基:https://en.wikipedia.org/wiki/Stoer%E2%80%93Wagner_algorithm 该算法的思想之一是:对于一个无向连通图,选定某两点s,t,以及该图的一个s-t割C,则"C是该图的全局最小割"是"C是s-t的最

POJ 2914 Minimum Cut 全局最小割

裸的全局最小割了吧 有重边,用邻接矩阵的时候要小心 #include<iostream> #include<cstdio> #include<bitset> #include<cstring> #define MOD 1000000007 #define maxn 509 using namespace std; int a[590][590],wage[maxn],in[maxn],vis[maxn]; int n,x,y,v; int find(int&

POJ2914 Minimum Cut【全局最小割】【Stoer-Wangner】

题目链接: http://poj.org/problem?id=2914 题目大意: 提一个无向有重边的图,有重边的边权累加起来,求全局最小割. 思路: 一个无向连通图,去掉一个边集可以使其变成两个连通分量则这个边集就是割集.最小割 集当然就是权和最小的割集. 这是一个最简单的全局最小割模板题.直接套上模板就可以了.来说说Stoer-Wangner算 法吧. Stoer-Wangner算法: 对于图中的任意两个顶点u和v,若u,v属于最小割的同一个集合中,那么僵顶点u和顶点 v合并后并不影响图的

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

POJ2914 Minimum Cut 最小割集

题目大意是,给定N个顶点,M条边,两个顶点之间可能有多条边,求至少删除多少条边才能将该图分成两个子图. 最小割集,典型的算法Stoer-Wagner,就是那篇论文,这里也就不复制过来了,只是用Prim求最大生成树时,更新的"边"不是普通意义上的边,而是顶点到所有已划分集合中的所有点的边权值和,这里要特别注意~ 直接贴代码~ #include <stdio.h> #include <vector> #include <math.h> #include

图的全局最小割的Stoer-Wagner算法及例题

Stoer-Wagner算法基本思想:如果能求出图中某两个顶点之间的最小割,更新答案后合并这两个顶点继续求最小割,到最后就得到答案. 算法步骤: ------------------------------------------------------------------------------------------------------------------------- (1)首先初始化,设最小割ans = INF                                

全局最小割 学习总结

全局最小割的意思是在一个无向图中任取S和T,求最小割的最小值 还有一种描述是删掉无向图中的边使得其不连通的最小代价 当然,这种题目可以用分治+最小割来求解 但是时间复杂度大约在O(n^4)左右 有一种更好的求解方法可以在O(n^3)的时间复杂度内求解 做法是这样的: 首先对于图中任意两点S->T 要么S和T不在一个集合里时是答案,答案显然是S和T的最小割 否则S和T在一个集合里,我们可以将S和T缩成一个点,不难证明这样是等效的 我们模拟这个过程,每次任取S和T跑最小割,时间复杂度大概跟分治+最小

UVALive 5099 Nubulsa Expo 全局最小割 非网络流 n^3

题目链接:点击打开链接 题意: 给定n个点m条无向边 源点S 下面m行给出无向边以及边的容量. 问: 找一个汇点,使得图的最大流最小. 输出最小的流量. 思路: 最大流=最小割. 所以题意就是找全局最小割. 和源点无关,因为不关心源点在哪个点集里. 模版题: O(n^3) #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> using namespace std

poj 2914 Minimum Cut 无向图最小边割

题意: 求无向图的全局最小边割. 分析: stoer-wagner模板. 代码: //poj 2914 //sep9 #include <iostream> using namespace std; const int maxN=512; int g[maxN][maxN]; int b[maxN],dist[maxN]; int n,m; int Min_Cut_Phase(int ph,int &x,int &y) { int i,j,t; t=1; b[1]=ph; fo