ACM必做50题的解题-最小生成树
BZOJ Solution—ACM题解

1013: [JSOI2008]球形空间产生器 sphere
这道题主要是构造出方程组,然后用高斯消元。我们设输入矩阵的第 i 行第 j 列的元素值为 ai , j ,我们所求的
第 2 页 共 96 页
2 坐标为 xi。则: ∀2 ≤ k ≤ n + 1 ,有 ∑ ( xi − a1,i ) = ∑ ( xi − ak ,i ) ,整理得 ∑ 2 xi × ( ak ,i − a1,i ) = ∑ ( ak2,i − a1, i ) 。接下来 2 2 i =1 i =1 i =1 i =1
Nim 博弈问题。我们分两种情况,如果全是 1 的话,如果是奇数个则是 Brother 否则是 John。如果不全是 1 的话,记 p 为所有石子数量的 xor 和,若 p 为 0 则是 Brother 否则是 John。
1024: [SCOI2009]生日快乐
爆搜就行了,以长为例,设长为 a,分成 k 分,那么分点一定是 ia/k。
1004: [HNOI2008]Cards
1, 2,..., n 我们对这 m+1 种情况分别计算答案, 由 Burnside 设题目一共给出了 m 种置换, 我们再加上一个 , 1, 2,..., n
引理知,最终的结果为
∑ f (i )
i =1
m +1
m +1
,其中 f(i)表示第 i 种置换的不动点个数。我们设第 i 种置换共有 T 个循环,则对
g[i ] i− f [i ] 2 × + = m[i + T ] g[i ] j m [ i ] i +T − 2
m[ j ] ∑ j = g [ i ]+1 i + T −
ACM必须掌握的算法

ACM必须的算法1.最短路(Floyd、Dijstra,BellmanFord)2.最小生成树(先写个prim,kruscal要用并查集,不好写)3.大数(高精度)加减乘除4.二分查找. (代码可在五行以内)5.叉乘、判线段相交、然后写个凸包.6.BFS、DFS,同时熟练hash表(要熟,要灵活,代码要简)7.数学上的有:辗转相除(两行内),线段交点、多角形面积公式.8. 调用系统的qsort, 技巧很多,慢慢掌握.9. 任意进制间的转换第二阶段:练习复杂一点,但也较常用的算法。
:1. 二分图匹配(匈牙利),最小路径覆盖2. 网络流,最小费用流。
3. 线段树.4. 并查集。
5. 熟悉动态规划的各个典型:LCS、最长递增子串、三角剖分、记忆化dp6.博弈类算法。
博弈树,二进制法等。
7.最大团,最大独立集。
8.判断点在多边形内。
9. 差分约束系统. 10. 双向广度搜索、A*算法,最小耗散优先.相关的知识图论:路径问题 0/1边权最短路径 BFS 非负边权最短路径(Dijkstra)可以用Dijkstra解决问题的特征负边权最短路径Bellman-Ford Bellman-Ford的Yen-氏优化差分约束系统 Floyd 广义路径问题传递闭包极小极大距离 / 极大极小距离 EulerPath / Tour 圈套圈算法混合图的 Euler Path / TourHamilton Path / Tour 特殊图的Hamilton Path / Tour 构造生成树问题最小生成树第k小生成树最优比率生成树 0/1分数规划度限制生成树连通性问题强大的DFS算法无向图连通性割点割边二连通分支有向图连通性强连通分支 2-SAT最小点基有向无环图拓扑排序有向无环图与动态规划的关系二分图匹配问题一般图问题与二分图问题的转换思路最大匹配有向图的最小路径覆盖0 / 1矩阵的最小覆盖完备匹配最优匹配稳定婚姻网络流问题网络流模型的简单特征和与线性规划的关系最大流最小割定理最大流问题有上下界的最大流问题循环流最小费用最大流 / 最大费用最大流弦图的性质和判定组合数学解决组合数学问题时常用的思想逼近递推 / 动态规划概率问题Polya定理计算几何 / 解析几何计算几何的核心:叉积 / 面积解析几何的主力:复数基本形点直线,线段多边形凸多边形 / 凸包凸包算法的引进,卷包裹法Graham扫描法水平序的引进,共线凸包的补丁完美凸包算法相关判定两直线相交两线段相交点在任意多边形内的判定点在凸多边形内的判定经典问题最小外接圆近似O(n)的最小外接圆算法点集直径旋转卡壳,对踵点多边形的三角剖分数学 / 数论最大公约数Euclid算法扩展的Euclid算法同余方程 / 二元一次不定方程同余方程组线性方程组高斯消元法解mod 2域上的线性方程组整系数方程组的精确解法矩阵行列式的计算利用矩阵乘法快速计算递推关系分数分数树连分数逼近数论计算求N的约数个数求phi(N)求约数和快速数论变换……素数问题概率判素算法概率因子分解数据结构组织结构二叉堆左偏树二项树胜者树跳跃表样式图标斜堆reap统计结构树状数组虚二叉树线段树矩形面积并圆形面积并关系结构Hash表并查集路径压缩思想的应用 STL中的数据结构vectordequeset / map动态规划 / 记忆化搜索动态规划和记忆化搜索在思考方式上的区别最长子序列系列问题最长不下降子序列最长公共子序列最长公共不下降子序列一类NP问题的动态规划解法树型动态规划背包问题动态规划的优化四边形不等式函数的凸凹性状态设计规划方向线性规划常用思想二分最小表示法串KMPTrie结构后缀树/后缀数组 LCA/RMQ有限状态自动机理论排序选择/冒泡快速排序堆排序归并排序基数排序拓扑排序排序网络中级:一.基本算法:(1)C++的标准模版库的应用. (poj3096,poj3007)(2)较为复杂的模拟题的训练(poj3393,poj1472,poj3371,poj1027,poj2706)二.图算法:(1)差分约束系统的建立和求解. (poj1201,poj2983)(2)最小费用最大流(poj2516,poj2516,poj2195)(3)双连通分量(poj2942)(4)强连通分支及其缩点.(poj2186)(5)图的割边和割点(poj3352)(6)最小割模型、网络流规约(poj3308, )三.数据结构.(1)线段树. (poj2528,poj2828,poj2777,poj2886,poj2750)(2)静态二叉检索树. (poj2482,poj2352)(3)树状树组(poj1195,poj3321)(4)RMQ. (poj3264,poj3368)(5)并查集的高级应用. (poj1703,2492)(6)KMP算法. (poj1961,poj2406)四.搜索(1)最优化剪枝和可行性剪枝(2)搜索的技巧和优化 (poj3411,poj1724)(3)记忆化搜索(poj3373,poj1691)五.动态规划(1)较为复杂的动态规划(如动态规划解特别的施行商问题等)(poj1191,poj1054,poj3280,poj2029,poj2948,poj1925,poj3034)(2)记录状态的动态规划. (POJ3254,poj2411,poj1185)(3)树型动态规划(poj2057,poj1947,poj2486,poj3140)六.数学(1)组合数学:1.容斥原理.2.抽屉原理.3.置换群与Polya定理(poj1286,poj2409,poj3270,poj1026).4.递推关系和母函数.(2)数学.1.高斯消元法(poj2947,poj1487,poj2065,poj1166,poj1222)2.概率问题. (poj3071,poj3440)3.GCD、扩展的欧几里德(中国剩余定理) (poj3101)(3)计算方法.1.0/1分数规划. (poj2976)2.三分法求解单峰(单谷)的极值.3.矩阵法(poj3150,poj3422,poj3070)4.迭代逼近(poj3301)(4)随机化算法(poj3318,poj2454)(5)杂题.(poj1870,poj3296,poj3286,poj1095)七.计算几何学.(1)坐标离散化.(2)扫描线算法(例如求矩形的面积和周长并,常和线段树或堆一起使用).(poj1765,poj1177,poj1151,poj3277,po j2280,poj3004)(3)多边形的内核(半平面交)(poj3130,poj3335)(4)几何工具的综合应用.(poj1819,poj1066,poj2043,poj3227,poj2165,poj3429)高级:一.基本算法要求:(1)代码快速写成,精简但不失风格(poj2525,poj1684,poj1421,poj1048,poj2050,poj3306)(2)保证正确性和高效性. poj3434二.图算法:(1)度限制最小生成树和第K最短路. (poj1639)(2)最短路,最小生成树,二分图,最大流问题的相关理论(主要是模型建立和求解)(poj3155,poj2112,poj1966,poj3281,poj1087,poj2289,poj3216,poj2446(3)最优比率生成树. (poj2728)(4)最小树形图(poj3164)(5)次小生成树.(6)无向图、有向图的最小环三.数据结构.(1)trie图的建立和应用. (poj2778)(2)LCA和RMQ问题(LCA(最近公共祖先问题) 有离线算法(并查集+dfs) 和在线算法(RMQ+dfs)).(poj1330)(3)双端队列和它的应用(维护一个单调的队列,常常在动态规划中起到优化状态转移的目的). (poj2823)(4)左偏树(可合并堆).(5)后缀树(非常有用的数据结构,也是赛区考题的热点).(poj3415,poj3294)四.搜索(1)较麻烦的搜索题目训练(poj1069,poj3322,poj1475,poj1924,poj2049,poj3426)(2)广搜的状态优化:利用M进制数存储状态、转化为串用hash表判重、按位压缩存储状态、双向广搜、A*算法.(poj1768,poj1184,poj1872,poj1324,poj2046,poj1482)(3)深搜的优化:尽量用位运算、一定要加剪枝、函数参数尽可能少、层数不易过大、可以考虑双向搜索或者是轮换搜索、IDA*算法. (poj3131,poj2870,poj2286)五.动态规划(1)需要用数据结构优化的动态规划.(poj2754,poj3378,poj3017)(2)四边形不等式理论.(3)较难的状态DP(poj3133)六.数学(1)组合数学.1.MoBius反演(poj2888,poj2154)2.偏序关系理论.(2)博奕论.1.极大极小过程(poj3317,poj1085)2.Nim问题.七.计算几何学.(1)半平面求交(poj3384,poj2540)(2)可视图的建立(poj2966)(3)点集最小圆覆盖.(4)对踵点(poj2079)八.综合题.(poj3109,poj1478,poj1462,poj2729,poj2048,poj333 6,poj3315,poj2148,poj1263)初期:一.基本算法:(1)枚举. (poj1753,poj2965) (2)贪心(poj1328,poj2109,poj2586)(3)递归和分治法. (4)递推.(5)构造法.(poj3295) (6)模拟法.(poj1068,poj2632,poj1573,poj2993,poj2996)二.图算法:(1)图的深度优先遍历和广度优先遍历.(2)最短路径算法(dijkstra,bellman-ford,floyd,heap+dijkstra)(poj1860,poj3259,poj1062,poj2253,poj1125,po j2240)(3)最小生成树算法(prim,kruskal)(poj1789,poj2485,poj1258,poj3026)(4)拓扑排序 (poj1094)(5)二分图的最大匹配 (匈牙利算法) (poj3041,poj3020)(6)最大流的增广路算法(KM算法). (poj1459,poj3436)三.数据结构.(1)串 (poj1035,poj3080,poj1936)(2)排序(快排、归并排(与逆序数有关)、堆排)(poj2388,poj2299)(3)简单并查集的应用.(4)哈希表和二分查找等高效查找法(数的Hash,串的Hash)(poj3349,poj3274,POJ2151,poj1840,poj2002,po j2503)(5)哈夫曼树(poj3253)(6)堆(7)trie树(静态建树、动态建树) (poj2513)四.简单搜索(1)深度优先搜索(poj2488,poj3083,poj3009,poj1321,poj2251)(2)广度优先搜索(poj3278,poj1426,poj3126,poj3087.poj3414)(3)简单搜索技巧和剪枝(poj2531,poj1416,poj2676,1129)五.动态规划(1)背包问题. (poj1837,poj1276)(2)型如下表的简单DP(可参考lrj的书 page149):1.E[j]=opt{D+w(i,j)}(poj3267,poj1836,poj1260,poj2533)2.E[i,j]=opt{D[i-1,j]+xi,D[i,j-1]+yj,D[i-1][j-1 ]+zij} (最长公共子序列)(poj3176,poj1080,poj1159)3.C[i,j]=w[i,j]+opt{C[i,k-1]+C[k,j]}.(最优二分检索树问题)六.数学(1)组合数学:1.加法原理和乘法原理.2.排列组合.3.递推关系.(POJ3252,poj1850,poj1019,poj1942)(2)数论.1.素数与整除问题2.进制位.3.同余模运算.(poj2635, poj3292,poj1845,poj2115)(3)计算方法.1.二分法求解单调函数相关知识.(poj3273,poj3258,poj1905,poj3122)七.计算几何学.(1)几何公式.(2)叉积和点积的运用(如线段相交的判定,点到线段的距离等). (poj2031,poj1039)(3)多边型的简单算法(求面积)和相关判定(点在多边型内,多边型是否相交)(poj1408,poj1584)(4)凸包. (poj2187,poj1113)。
acm常用板子题

acm常用板子题
ACM常用模板题包括但不限于:
字符串操作:如字符串匹配、字符串排序、字符串还原等题目,需要熟练掌握字符串的基本操作和常用算法。
数组操作:如数组排序、数组查找、数组分割等题目,需要熟练掌握数组的基本操作和常用算法。
树形结构:如二叉树、AVL树、红黑树等题目,需要熟练掌握树形结构的基本操作和常用算法。
图论算法:如最短路径、最小生成树、拓扑排序等题目,需要熟练掌握图论算法的基本操作和常用算法。
动态规划:如背包问题、最长公共子序列、最长递增子序列等题目,需要熟练掌握动态规划的基本操作和常用算法。
搜索算法:如深度优先搜索、广度优先搜索等题目,需要熟练掌握搜索算法的基本操作和常用算法。
数据结构:如哈希表、并查集、线段树等题目,需要熟练掌握数据结构的基本操作和常用算法。
以上是一些常见的ACM模板题,当然还有很多其他的题目类型。
要提高自己的ACM水平,需要多做题、多思考、多总结,不断拓宽自己的算法和数据结构知识面。
算法竞赛入门经典训练指南题单

算法竞赛入门经典训练指南题单全文共四篇示例,供读者参考第一篇示例:算法竞赛作为计算机科学领域中的重要领域之一,一直备受关注和推崇。
参加算法竞赛可以帮助我们提高编程能力、思维灵活性和解决问题的能力。
而且,通过算法竞赛,我们还可以结识来自各个国家的优秀程序员,开阔自己的视野,提高自己的竞争力。
而要在算法竞赛中取得好成绩,就需要有一定的训练和积累。
本文将为大家推荐一些经典的算法竞赛训练题单,希望能帮助大家快速入门和提升自己的算法竞赛水平。
1. ACM-ICPC题单ACM国际大学生程序设计竞赛(ACM-ICPC)是全球规模最大、最具影响的大学生程序设计竞赛,被誉为程序设计界的“奥林匹克”。
ACM-ICPC赛题难度较高,对参赛者的编程能力、算法设计能力和团队协作能力等方面都有严格的要求。
参加ACM-ICPC的同学们需要有一定的训练和备战。
以下是一些经典的ACM-ICPC训练题单,推荐给大家:1、CodeforcesCodeforces是一个国际知名的在线编程比赛和训练平台,其比赛难度较高,同时也有很大的影响力。
在Codeforces上,你可以找到各种难度的题目,从入门级到专家级都有覆盖。
推荐大家在Codeforces 上刷题,提高自己的编程能力和解题能力。
3、洛谷洛谷是国内著名的在线题库和训练平台,里面汇集了大量的ACM 竞赛题目和OJ题目,适合广大程序员练习和提升编程能力。
洛谷上的题目分类清晰,难度适中,非常适合新手入门和提高。
2. Google Code Jam题单Google Code Jam是由谷歌主办的一项全球性的编程大赛,是程序员们展示自己编程才华的绝佳舞台。
Google Code Jam的题目设计独特,难度适中,涵盖了很多经典的算法问题,非常适合有一定编程基础的程序员练习和挑战。
以下是一些推荐的Google Code Jam题单:LeetCode是一个在线的编程练习平台,里面包含了大量的算法和数据结构问题,适合练习和提升自己的编程能力。
北大ACM题型

3.C[i,j]=w[i,j]+opt{C[i,k-1]+C[k,j]}.(最优二分检索树问题)
六.数学
(1)组合数学:
1.加法原理和乘法原理.
2.排列组合.
3.递推关系. (POJ3252,poj1850,poj1019,poj1942)
(2)数论.
1.素数与整除问题
(2)扫描线算法(例如求矩形的面积和周长并,常和线段树或堆一起使用). (poj1765,poj1177,poj1151,poj3277,poj2280,poj3004)
(3)多边形的内核(半平面交)(poj3130,poj3335)
(4)几何工具的综合应用.(poj1819,poj1066,poj2043,poj3227,poj2165,poj3429)
(2)记录状态的动态规划. (POJ3254,poj2411,poj1185)
(3)树型动态规划(poj2057,poj1947,poj2486,poj3140)
六.数学
(1)组合数学:
1.容斥原理.
2.抽屉原理.
3.置换群与Polya定理(poj1286,poj2409,poj3270,poj1026).
五.动态规划
(1)需要用数据结构优化的动态规划. (poj2754,poj3378,poj3017)
(2)四边形不等式理论.
(3)较难的状态DP(poj3133)
六.数学
(1)组合数学.
1.MoBius反演(poj2888,poj2154)
2.偏序关系理论.
(2)博奕论.
----------------------------------------------------------------------------------------------- -----------------------------------补充 Dp状态设计与方程总结
最小生成树的概念

最小生成树的概念
在图论中,最小生成树是一个连通图的生成树,其边的权值之和最小。
通俗地说,最
小生成树是指在一个图中找到一棵权值最小的生成树,这个生成树包含了连通图的所有顶点,且边的数量最小。
怎么找到最小生成树呢?有两种常用算法:Prim算法和Kruskal算法。
Prim算法首先任选一个点作为起点,然后在剩余的点中选择与当前集合距离最短的点加入集合,直到所有点被加入。
在加入每一个点时,找到与当前集合连接的距离最短的边,加入到生成树中。
重复以上步骤,直到所有点都被加入到生成树中。
Kruskal算法则是将边按照权值从小到大排序,选择权值最小的边加入到生成树中,
如果加入当前边后不构成环,则加入,否则继续找下一条权值最小的边。
重复以上步骤,
直到所有点都被加入到生成树中。
最小生成树有很广泛的应用,如在通信、传输、路网规划等领域都有很重要的作用。
在有些应用中,最小生成树不仅要求边的权值之和最小,还要满足一些约束条件,比如边
的数量、每个点的度数等,这时我们需要采用更加复杂的算法来求解问题。
最小生成树的应用非常广泛,比如在计算机网络中,路由协议需要找到最短的数据传
输路径;在城市交通中,规划出最优的交通路径能够有效减少能源的消耗;在电力系统中,设计最短的输电线路可以节省能源成本。
最小生成树的运用如此广泛,它不仅在计算机科
学中有重要作用,也在其他各个领域有着不可替代的作用。
北大 poj acm题目推荐50题

-北大poj acm题目推荐50题POJ == 北京大学ACM在线评测系统/JudgeOnline1. 标记难和稍难的题目大家可以看看,思考一下,不做要求,当然有能力的同学可以直接切掉。
2. 标记为A and B 的题目是比较相似的题目,建议大家两个一起做,可以对比总结,且二者算作一个题目。
3. 列表中大约有70个题目。
大家选做其中的50道,且每类题目有最低数量限制。
4. 这里不少题目在BUPT ACM FTP 上面都有代码,请大家合理利用资源。
5. 50个题目要求每个题目都要写总结,养成良好的习惯。
6. 这50道题的规定是我们的建议,如果大家有自己的想法请与我们Email 联系。
7. 建议使用C++ 的同学在POJ 上用G++ 提交。
8. 形成自己编写代码的风格,至少看上去美观,思路清晰(好的代码可以很清楚反映出解题思路)。
9. 这个列表的目的在于让大家对各个方面的算法有个了解,也许要求有些苛刻,教条,请大家谅解,这些是我们这些年的经验总结,所以也请大家尊重我们的劳动成果。
10. 提交要求:一个总文件夹名为bupt0xx (即你的比赛帐号), 这个文件夹内有各个题目类别的子目录(文件夹),将相应的解题报告放入对应类别的文件夹。
在本学期期末,小学期开始前,将该文件夹的压缩包发至buptacm@。
对于每个题目只要求一个POJxxxx.cpp 或POJxxxx.java (xxxx表示POJ该题题号) 的文件,注意不要加入整个project 。
11. 如果有同学很早做完了要求的题目,请尽快和我们联系,我们将指导下一步的训练。
下面是一个解题报告的范例:例如:POJ1000.cpp//考查点:会不会编程序。
//思路:此题要求输入两个数,输出两个数的和,我用scanf 和printf。
//提交情况:Wrong Answer 1次,忘了写printf()。
Compile Error 2次,选错了语言,由于C++ 和G++ 在iostream.h 的不用引用方法;少一个大括号。
ACM基础算法入门教程

ACM基础算法入门教程ACM(ACM International Collegiate Programming Contest)是国际大学生程序设计竞赛的缩写,被认为是计算机领域最有权威和最具挑战性的竞赛之一、ACM竞赛要求参赛者在规定的时间内,根据给出的问题,编写出能在规定时间内运行并给出正确答案的程序。
参加ACM竞赛不仅可以锻炼算法思维,提高编程实力,还可以拓宽知识领域和增加竞争力。
在这个ACM基础算法入门教程中,我们将介绍一些常用的基础算法和数据结构,帮助初学者更好地理解和掌握ACM竞赛所需的算法知识。
一、排序算法排序算法是ACM竞赛中最常用的算法之一,能够帮助我们按照一定的规则将数据进行排序,从而解决一些需要有序数据的问题。
1.冒泡排序:通过多次比较和交换来实现,每次迭代将最大的值沉到最底部。
2.快速排序:选择一个基准元素将数组分为两部分,一部分都小于基准元素,一部分都大于基准元素,递归排序子数组。
3.归并排序:将数组不断二分,将相邻两个子数组排序后再合并成一个有序数组。
4.插入排序:从第二个元素开始,依次将元素插入已排序的子数组中。
二、查找算法查找算法可以帮助我们在一组数据中找到目标元素,从而解决一些需要查找特定数据的问题。
1.顺序查找:逐个扫描数据,直到找到目标元素或扫描结束为止。
2.二分查找:对已排序的数组进行查找,不断将数组二分直到找到目标元素的位置。
3.哈希查找:通过计算数据的哈希值找到对应的存储位置,实现快速查找。
三、字符串匹配算法字符串匹配算法可以帮助我们在一组字符串中寻找特定模式的子字符串,从而解决一些需要在字符串中查找其中一种规律的问题。
1.暴力匹配算法:对目标字符串的每个位置,逐个将模式串进行匹配,直到找到或匹配结束为止。
2.KMP算法:通过已匹配的部分信息,尽量减少字符比较的次数。
3. Boyer-Moore算法:通过预先计算模式串中每个字符最后出现位置的表格,以及坏字符规则和好后缀规则,来实现快速匹配。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
POJ 1251 Jungle Roads小感:第一次做图论题目,而且一次就AC了,挺兴奋的,呵呵。
当然,还有很多不是非常明白的地方,对算法很细节的执行还没有非常明白~还有就是,Prim算法的过程好像是选出一个点后,找该点与剩下的点的权值的最小值,而不是所有在U中的点与V-U中的点的最小值。
开始时觉得应该是所有U中的与V-U中最小的值的~还得再看看~这里用了Prim求最小生成树,图是用邻接矩阵表示的,算法复杂度为O(n2),其实看书上的例子,是用邻接表实现的,而且用到了最小堆求权值最小的边,最后的复杂度为O(elog2e),e为边数。
总的过程是从V-U中选出到U中权值最小的点,并加到U,之后更新lowcost,被更新的lowcost只是在V-U中的。
还有就是关于scanf,开始时用,可是在输入的时候有问题,不知道怎么回事~看别人也都说scanf会RE等的,于是用了cin,结果0MS就可以过了~还有,也看到有人说用了26时,RE 了,所以我就改成27了,也不知道26到底会不会错~#include <iostream>#define MAX 27#define MAXCOST 101using namespace std;int vertices[MAX],lowcost[MAX],minv,totalcost;int edges[MAX][MAX];bool visited[MAX];int prim(int vertex_num,int v){totalcost=0;visited[v]=true;for(int i=0;i<vertex_num;i++)lowcost[i]=edges[v][i];for(int i=1;i<vertex_num;i++){minv=MAXCOST;//for选出从U中顶点到V-U中顶点的最小权值,每次从第一个开始//这样如果碰到边界顶点时,可以回到另外的点for(int j=0;j<vertex_num;j++)if(visited[j]==false&&lowcost[j]<minv)//lowcost[j]是从顶点v到顶点j的权值{minv=lowcost[j];v=j;}visited[v]=true;totalcost+=minv;for(int j=0;j<vertex_num;j++)if(visited[j]==false&&edges[v][j]<lowcost[j])lowcost[j]=edges[v][j];}return totalcost;}int main(){int num,degree,cost;char vertex;while(cin>>num){if(num==0) break;for(int i=0;i<num;i++) vertices[i]=i;for(int i=0;i<num;i++)for(int j=0;j<num;j++)edges[i][j]=MAXCOST;for(int i=0;i<num;i++) visited[i]=false;for(int i=0;i<num-1;i++){cin>>vertex>>degree;for(int j=0;j<degree;j++){cin>>vertex>>cost;edges[i][vertex-'A']=cost;edges[vertex-'A'][i]=cost;}}cout<<prim(num,0)<<endl;}return 0;}POJ 1258 Agri-NetSlyar:简单介绍一下题意。
农民要建立互联网络,目的使村庄里所有的农民连上网,并且总费用最小。
多组数据,每组数据给出一个n,然后给出n * n大小的无向图的邻接矩阵表示,值表示边权。
要求输出最小生成树的权值和。
这次用朴素的Prim写。
Prim详见/blog/prim-simplicity-c.html#include <stdio.h>#include <stdlib.h>#define MAX 101#define MAXCOST 0x7fffffffint graph[MAX][MAX];int Prim(int graph[][MAX], int n){int lowcost[MAX];int mst[MAX];int i, j, min, minid, sum = 0;for (i = 2; i <= n; i++){lowcost[i] = graph[1][i];mst[i] = 1;}mst[1] = 0;for (i = 2; i <= n; i++){min = MAXCOST;minid = 0;for (j = 2; j <= n; j++){if (lowcost[j] < min && lowcost[j] != 0){min = lowcost[j];minid = j;}}sum += min;lowcost[minid] = 0;for (j = 2; j <= n; j++){if (graph[minid][j] < lowcost[j]){lowcost[j] = graph[minid][j];mst[j] = minid;}}}return sum;}int main(){int i, j, k, m, n;int cost;while (scanf("%d", &n) != EOF){for (i = 1; i <= n; i++){for (j = 1; j <= n; j++){graph[i][j] = MAXCOST;}}for (i = 1; i <= n; i++){for (j = 1; j <= n; j++){scanf("%d", &graph[i][j]);}}cost = Prim(graph, n);printf("%d\n", cost);}return 0;}POJ 1789 Truck History 最小生成树题意:n的卡车,每辆车拥有唯一的7位车牌号。
两两之间车牌号的有几位不相同就表示有多大的差别,即两代之间的距离有多远,求联通所有带的最短距离和。
题解:理解题意后不难发现就是一个简单的最小生成树。
和原来低效的prim写法不同的是用mdis [i]来更新到每个点的最小边,这样可以省去一层循环。
#include <stdio.h>#include <stdlib.h>#include <string.h>#define MAX 99999int n,dis[2010][2010],in[2010],dif,ans,mdis[2010];char a[2010][7];void prim(){int i,j,k,min,v;ans = 0;memset(in,0,sizeof(in));in[1] =1 ;for (i=1;i<=n;i++)mdis[i] = dis[1][i];for (i=1;i<n;i++){min = MAX;for (j=1;j<=n;j++)if (!in[j] && mdis[j]<min){v = j;min = mdis[j];}ans += min;if (!in[v]) in[v] = 1;for (k=1;k<=n;k++)if (!in[k] && mdis[k]>dis[v][k])mdis[k] = dis[v][k];}}int main()int i,j,k;while (scanf("%d", &n),n){getchar();for (i=1;i<=n;i++){gets(a[i]);for (j=1;j<i;j++){dif = 0;for (k=0;k<7;k++)if (a[i][k]!=a[j][k])dif++;dis[i][j] = dis[j][i] = dif;}dis[i][i] = MAX;}prim();printf("The highest possible quality is 1/%d.\n", ans);}}POJ 2485 Highways一看就知是最小生成树,开始的时候用Kruskal出问题,改用Prim过了POJ,现在回过头来用Kruskal算法做,也好,又过了。
发出来,或许也会有像我这样曾经被这个问题搞郁闷的朋友。
问题抽象一个下就是求Kruskal算法中最后加入的那条边的长度,同样是Prim算法中加入的边的最长的那条。
prim解法:#include <iostream>using namespace std;int highway[501][501];int lowcost[501], n;int prim(){for(int i = 1; i <= n; i++)lowcost[i] = highway[1][i];int ans = 0, nextVex, minEdge;for(int i = 1; i < n; i++){minEdge = 999999999;nextVex = 1;for(int j = 1; j <= n; j++){if((lowcost[j] < minEdge) && (lowcost[j] > 0)){minEdge = lowcost[j];nextVex = j;}}if(minEdge > ans)ans = minEdge;lowcost[nextVex] = 0;for(int j = 1; j <= n; j++){if(lowcost[j] > highway[nextVex][j]){lowcost[j] = highway[nextVex][j];}}}return ans;}int main(){int tcase;scanf("%d", &tcase);while(tcase--){scanf("%d", &n);for(int i = 1; i <= n; i++)for(int j = 1; j <= n; j++)scanf("%d", &highway[i][j]);printf("%d\n", prim());}return 0;}。