POJ 2914 Minimum Cut 最小割图论

POJ 2914 Minimum Cut 最小割图论

大家好,又见面了,我是全栈君,今天给大家准备了Idea注册码。

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 integers AB 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)

本题是06年百度之星半决赛的题目,图论的最小割问题。算是图论高级内容吧。

Stoer Wager算法,当中的难点是:

1 逐条边查找最大的边的权值-过程有点想Prime算法,只是实际上不是Prime算法,由于目的并非最大生成树,而是须要把一个顶点的全部边都加起来。把这些边去掉,就是这个顶点的割点值了。那么就须要遍历整个图,到了最后一个节点才干保证是找到了这个节点的全部边。

2 缩点:所谓缩点就是把最后一个节点去掉,同一时候保留其边值信息,实际就是保留这个顶点的和其它顶点相连的最小边值。

比較难理解的,一般写这个题解报告的博客,一个是要么直接抄模板了。二是要么没有讲解;三个是有了几句讲解了。结果都没理解好,甚至错误;

也是非常难说清楚的一个题目,看看我具体凝视的程序吧。

#include <stdio.h>
#include <string.h>
#include <limits.h>
#include <algorithm>
using namespace std;

const int MAX_N = 501;
int gra[MAX_N][MAX_N];//矩阵表示图

bool shrinkedVertices[MAX_N];//标志那些顶点已经被缩点了
bool vis[MAX_N];//标志当前那些节点已经訪问了
int dis[MAX_N];//记录最大距离
int lastSec, last;//记录每次最后cut边的两个顶点
int getLastCut(int leftVertices, int n)//每次计算剩下多少没缩点的顶点计算就可以
{
	fill(dis, dis+n, 0);
	fill(vis, vis+n, false);
	int curVer = 0;//curVer代表当前选取的顶点,初始为选取0顶点
	lastSec = last = 0;

	//循环的主要作用的把一个顶点的全部边都加起来。仅仅有在最后一次选择的时候才干确保最后一个顶点的全部边都加起来了。
	for (int i = 1; i < leftVertices; i++)
	{//操作的是边。边比顶点少1的,故此i从1開始,不是从0開始
		for (int v = 1; v < n; v++)
		{//0顶点已经最先选择了,故此v从1開始,不是从0開始
			if (!vis[v] && !shrinkedVertices[v]) dis[v] += gra[v][curVer];
		}//主要是把一个顶点的全部边都加起来
		int maxCut = 0;
		//选取当前最大的割边。未到最后一点。不能保证是真正的割边
		for (int v = 1; v < n; v++)
		{
			if (!vis[v] && !shrinkedVertices[v] && dis[v] > maxCut)
			{
				maxCut = dis[v];
				curVer = v;
			}
		}
		if (!maxCut) return 0;//本来就是分隔图,割边能够为零了。

vis[curVer] = true; lastSec = last; last = curVer;//逐次保存最后两个顶点 } return dis[last];}int Stoer_Wagner(int n){ fill(shrinkedVertices, shrinkedVertices+n, false); int minCut = INT_MAX; for (int i = n; i > 1; i--) { minCut = min(minCut, getLastCut(i, n)); if (!minCut) return 0; shrinkedVertices[last] = true; for (int v = 0; v < n; v++) { if (!shrinkedVertices[v]) gra[lastSec][v] = gra[v][lastSec] += min(gra[v][last], gra[last][lastSec]);//事实上缩点就是保留当中一段边,须要保留最小值边,确保是最小割。 } } return minCut == INT_MAX? 0 : minCut;}int main(){ int N, M, u, v, w; while (~scanf("%d %d", &N, &M)) { for (int i = 0; i < N; i++) { for (int j = 0; j < N; j++) { gra[i][j] = 0; } } for (int i = 0; i < M; i++) { scanf("%d %d %d", &u, &v, &w); gra[u][v] = gra[v][u] += w; } printf("%d\n", Stoer_Wagner(N)); } return 0;}

只是上面程序的效率不高。那么能够优化一下。优化的主要方法是,利用一个数组保存好剩下的顶点,那么缩点的时候直接删除这个顶点。就不用下一次还须要遍历推断这个顶点。

这样优化了常数项,实际执行时间快了2到3倍左右,效果非常好。

#include <stdio.h>
#include <string.h>
#include <limits.h>
#include <algorithm>
using namespace std;

const int MAX_N = 501;
int gra[MAX_N][MAX_N];
int vps[MAX_N];
bool vis[MAX_N];
int dis[MAX_N];
int last, sec;

int getLastCut(int V)
{
	fill(vis, vis+V, false);
	fill(dis, dis+V, 0);
	last = sec = 0;
	int id = 0;
	for (int i = 1; i < V; i++)
	{
		int v = vps[id];
		for (int j = 1; j < V; j++)
		{
			if (!vis[j]) dis[j] += gra[v][vps[j]];
		}
		int m = 0;
		for (int j = 1; j < V; j++)
		{
			if (!vis[j] && m < dis[j]) m = dis[j], id = j;
		}
		if (!m) return 0;
		vis[id] = true;
		sec = last; last = vps[id];
	}
	swap(vps[id], vps[V-1]);
	return dis[id];
}

int Stoer_wagner(int n)
{
	for (int i = 0; i < n; i++) vps[i] = i;
	int minCut = INT_MAX;
	for (int V = n; V > 1; V--)
	{
		minCut = min(minCut, getLastCut(V));
		if (!minCut) return 0;
		for (int i = 0; i < V; i++)
		{
			int v = vps[i];
			gra[v][sec] = gra[sec][v] += min(gra[v][last], gra[last][sec]);
		}
	}
	return minCut == INT_MAX? 0 : minCut;
}

int main()
{
	int Ver, Edge, u, v, w;
	while (~scanf("%d %d", &Ver, &Edge))
	{
		for (int i = 0; i < Ver; i++)
			for (int j = 0; j < Ver; j++)
				gra[i][j] = 0;

		for (int i = 0; i < Edge; i++)
		{
			scanf("%d %d %d", &u, &v, &w);
			gra[u][v] = gra[v][u] += w;
		}
		printf("%d\n", Stoer_wagner(Ver));
	}
	return 0;
}

版权声明:笔者靖心脏,景空间地址:http://blog.csdn.net/kenden23/。只有经过作者同意转载。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/116766.html原文链接:https://javaforall.net

(0)
上一篇 2022年1月15日 下午9:00
下一篇 2022年1月15日 下午10:00


相关推荐

  • goland 2021.11.4 激活【中文破解版】

    (goland 2021.11.4 激活)JetBrains旗下有多款编译器工具(如:IntelliJ、WebStorm、PyCharm等)在各编程领域几乎都占据了垄断地位。建立在开源IntelliJ平台之上,过去15年以来,JetBrains一直在不断发展和完善这个平台。这个平台可以针对您的开发工作流进行微调并且能够提供…

    2022年3月29日
    50
  • pycharm入门教程(非常详细)_pycharm的用法

    pycharm入门教程(非常详细)_pycharm的用法PyCharmv2018.2最新版本下载 在PyCharm中使用IPython/JupyterNotebook在你开始之前在执行本教程的任务之前,请确保满足以下先决条件:您已经创建了一个Python项目。在本教程中,使用项目C:/SampleProjects/py/JupyterNotebookExample。 在Settings/Preferences对…

    2022年8月26日
    6
  • STM32独立看门狗

    STM32独立看门狗参考正点原子视频看门狗在由单片机构成的微型计算机系统中,由于单片机的工作常常会受到来自外界电磁场的干扰,造成程序的跑飞,而陷入死循环,程序的正常运行被打断,由单片机控制的系统无法继续工作,会造成整个系统的陷入停滞状态,发生不可预料的后果,所以出于对单片机运行状态进行实时监测的考虑,便产生了一种专门用于监测单片机程序运行状态的模块或者芯片,俗称:看门狗看门狗的意义在启动正常运行的时候,系统不能复位在系统跑飞(程序异常执行)的情况,系统复位,程序重新执行独立看门狗(IWDG)由专用的低速时钟(L

    2022年5月24日
    46
  • SSL VNP技术原理

    SSL VNP技术原理

    2021年4月15日
    159
  • 一旦你开始了新的工作,新的他们很可能也会要求你做这么白痴的事,如果不是更白痴的话(转)…

    一旦你开始了新的工作,新的他们很可能也会要求你做这么白痴的事,如果不是更白痴的话(转)…

    2021年9月3日
    54
  • 给 Pycharm 安装 pytorch

    给 Pycharm 安装 pytorch问题在之前的文章Win10通过Anaconda下载安装PyTorch中,用Anacondaprompt在base环境中安装了PyTorch,并且能在Jupyternotebook中调用。但遇到了两个问题:使用Pycharm创建新project时,envs目录下找不到pytorch的选项;在Pycharm中运行>>>importtorch报错“Couldnotfindcondaenvironment:torch”

    2022年8月27日
    11

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号