hdu1232另类解法Prim

2024-02-03 03:18
文章标签 prim 解法 另类 hdu1232

本文主要是介绍hdu1232另类解法Prim,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Problem Description
某省调查城镇交通状况,得到现有城镇道路统计表,表中列出了每条道路直接连通的城镇。省政府“畅通工程”的目标是使全省任何两个城镇间都可以实现交通(但不一定有直接的道路相连,只要互相间接通过道路可达即可)。问最少还需要建设多少条道路?

Input
测试输入包含若干测试用例。每个测试用例的第1行给出两个正整数,分别是城镇数目N ( < 1000 )和道路数目M;随后的M行对应M条道路,每行给出一对正整数,分别是该条道路直接连通的两个城镇的编号。为简单起见,城镇从1到N编号。
注意:两个城市之间可以有多条道路相通,也就是说
3 3
1 2
1 2
2 1
这种输入也是合法的
当N为0时,输入结束,该用例不被处理。

Output
对每个测试用例,在1行里输出最少还需要建设的道路数目。

Sample Input
4 2
1 3
4 3
3 3
1 2
1 3
2 3
5 2
1 2
3 5
999 0
0

Sample Output
1
0
2
998
最近有几个朋友问我这个题目,然后我就讲了我用Prim算法AC了,然而网上的大多参考代码都是用并查集做的。所以,作为一个补充,我想说说我自己的解法。(AC不需要标准答案,可能我这解法还没并查集高效,但分享出来吧。)然而作为一个刚玩几天的ACMer,还没学并查集,我当时看到这题目的时候。我觉得应该是用最小生成树做,不会并查集,所以首选Prim。

先上代码,你们先体会体会。

#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
const int INF=0x3f3f3f3f;//正无穷
const int MAXN=1010;
bool vis[MAXN];//记录该点是否被访问
int lowc[MAXN];//lowc[i]表示从当前树到i点的最小权值
int cost[MAXN][MAXN];//最初两点之间的权值
int flag;
int Prim(int n,int start)//点是0~n-1
{int ans=1;if(0==flag)//vis只在第一次调用Prim的时候初始化。{memset(vis,false,sizeof(vis));flag=1;}for(int i=1;i<n;i++)lowc[i]=cost[start][i];vis[start]=true;for(int i=1;i<n;i++){int minc=INF;int p=-1;for(int j=0;j<n;j++)if(!vis[j]&&minc>lowc[j]){minc=lowc[j];p=j;}if(minc==INF)//这里本来是判断图不连通的条件{for(int j=1;j<n;j++){if(!vis[j])ans+=Prim(n,j);}return ans;}vis[p]=true;for(int j=0;j<n;j++)if(!vis[j]&&lowc[j]>cost[p][j])lowc[j]=cost[p][j];}return ans;
}
int main()
{int n,m,a,b,i,j,ans;while(1){scanf("%d",&n);if(n==0)break;memset(cost,INF,sizeof(int)*MAXN*MAXN);scanf("%d",&m);if(m==0){cout<<n-1<<endl;continue;}for(i=0;i<m;i++){scanf("%d%d",&a,&b);cost[a-1][b-1]=1;cost[b-1][a-1]=1;}flag=0;ans=Prim(n,0)-1;cout<<ans<<endl;}
}

我这里用的点是[0, n-1],注意。

大体还是常规的Prim算法,Prim本来的返回值应该是最小生成树的权值,或者返回这不是一个连通图。我这里把它改了。Prim返回不是连通图时,已经是把所有能访问的点访问过了。所以在这里,我们选一个无法访问的点,继续Prim,然后递归进去。直到所有点都访问过了,然后一层一层返回。返回的值就是递归调用了几次Prim,所以就是把原来的图,用最小生成树的方式,变成了森林,所以只要树的棵树减1,就是最少还需要建的路的数量。

这篇关于hdu1232另类解法Prim的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/672834

相关文章

力扣刷题 杨辉三角(使用c++ vector解法)

杨辉三角 题目描述示例1示例2提示:代码 题目描述 给定一个非负整数 numRows,生成「杨辉三角」的前 numRows 行。 在「杨辉三角」中,每个数是它左上方和右上方的数的和。 示例1 输入: numRows = 5 输出: [[1],[1,1],[1,2,1],[1,3,3,1],[1,4,6,4,1]] 示例2 输入: numRows = 1

【java编程(在线笔试)】【链表】两道k个一组翻转链表题目(包含非递归和递归两种解法)

一、给你一个链表,每 k 个节点一组进行翻转,请你返回翻转后的链表。如果节点总数不是 k 的整数倍,那么请将最后剩余的节点也翻转顺序。 1. 非递归解法 /*** Definition for singly-linked list.* public class ListNode {* int val;* ListNode next;* ListNode(int x) {

每天刷个算法题20160525:快速排序的递归转非递归解法

版权所有。所有权利保留。 欢迎转载,转载时请注明出处: http://blog.csdn.net/xiaofei_it/article/details/51524798 为了防止思维僵化,每天刷个算法题。已经刷了几天了,现在发点代码。 我已经建了一个开源项目,每天的题目都在里面: https://github.com/Xiaofei-it/Algorithms

每天刷个算法题20160524:阿克曼函数的递归转非递归解法

版权所有。所有权利保留。 欢迎转载,转载时请注明出处: http://blog.csdn.net/xiaofei_it/article/details/51524754 为了防止思维僵化,每天刷个

【Rust 日报】2021-08-01 voila:另类处理文件的方式

voila:另类处理文件的方式 Voila 是一种通过 CLI 工具启动的特定领域语言,用于以快速可靠的方式处理大量文件和目录。 安装需要切换到 nightly 版本: $ rustup default nightly$ cargo install voila 一些使用实例: # 删除创建日期在 2020年1月1日 之后的所有文件$ voila ./backup "@creation=dat

C++蓝白点思想Prim算法(最小生成树 - 懒猫老师)

最小生成树Prim算法(C++蓝白点思想) 一、知识储备1.图的构造2.蓝白点思想 二、代码实现 一、知识储备   我们都知道,最小生成树的定义为:是原图的极小连通子图,包含图中所有结点,最重要的是保持图连通最少的边。❤️小白发文,若有不足欢迎大佬来斧正~ 1.图的构造   构造一个对象时,我们需要先了解清除其含有什么特征、什么特性,再去进行构造。在这里,图的构造也不

LeetCode第21题之Generate Parentheses(两种解法)

C++代码: 解法一(在LeetCode上运行效率高于解法二): #include <vector>#include <iostream>#include <string>using namespace std;class Solution {private:vector<string> res;public: //leftRemain保存还可以放左括号的数目,rightRemain

prim算法和kruskal算法详解

在我们的数据结构中,当涉及到图的寻找最小的路径时,不得不提到最经典的寻找图的最小生成树的算法: prim算法和kruskal算法详解。下面笔者将与大家共同探讨一下这两个经典的算法和他们的C++代码实现。 首先我们先看引自百度百科的prim算法的定义:普里姆算法(Prim算法),图论中的一种算法,可在加权连通图里搜索最小生成树。意即由此算法搜索到的边子集所构成的树中,不但包括了连通图里的所有顶点(英

反转链表的解法分享

1、双指针法 ListNode* addInList(ListNode* head1, ListNode* head2) {// write code hereListNode* ReverseList(ListNode* pHead){if(pHead == NULL)return NULL;ListNode* cur = pHead;ListNode* pre =NULL;while(cu

3Sum Closest问题及解法

问题描述: Given an array S of n integers, find three integers in S such that the sum is closest to a given number, target. Return the sum of the three integers. You may assume that each input would have