【转】【最小树形图】有向图的最小生成树【朱刘算法】
这篇文章挺好的。每行还有注释QAQ,kuangbin的模板里并没有万能节点;
万能节点好像是在不定根的时候的拓展。
要点:
1.求所有边权和sum;
2.以0点为万能节点向所有点建一条权值为sum的边;
3.记得sum++;保证比所有边权值总和大一点;
4.判断条件为(ans==-1 || ans-sum>=sum) //ans-sum是除去虚根的最小树形图的最短路径,如果这个距离比所有的边权值和sum还大,说明还有另外的边由虚点发出,故说明此图不连通
5.答案即为ans-sum;
最小树形图【有向图的最小生成树】 https://blog.csdn.net/qq_41730082/article/details/85338921
做了POJ的一道题,总是WA,不知道为什么,后来去看了,才知道,原来有向图的最小生成树与无向图不一样,它得是从某个点出发能遍历到其他所有点的才行,以此为条件,我们学习到了最小树形图。
与很多其他人的讲解不一样吧,我把我看了博客后自己的思路分享出来,关于什么是最小树形图。
我们知道的既然要建立最小树形图,就要理解什么是最小树形图,(概念好难懂啊,还是自己写的清楚明白),我们从某一点出发(或者是固定点),能通过它跑完所有点的最小花费,就是最小树形图了。
那么,怎么去搭建最小树形图?会有人看到关于最小弧这样的讲法,诶!确实是这样的,但是你们理解什么是最小弧吗?我们想构建一颗最小生成树的时候,就是找到这样的最优解的边逐条放进去的(Kruskal算法思想),但是这也是一样的,我们找到所有非根节点的最小入边,先把这样的所有入边给加进来,那么得到的一幅图,可能还真是不完全,要是遇到了个环,岂不是有趣,或者呢,压根就走不完!不就GG?所以,就这样就被我们想出了两个需要判断的条件了。
把所有的最小入边先加起来,我们得到了一个花里胡哨的图,可能它就是多个环的集合,也许恰好是答案,这都是不确定的,若是恰好是已经没有环了,那么这就是答案了;反之,就是有环,那么,我们得到的边,就不一定是所有的点构在一起的图(也许会成为森林这样的情况),那么,把环搜索起来吧,我们把一个环搜索成一个点,然后对于它(新点——即所谓的缩点)的入边,我们建立新边的时候,需要考虑到我们得删除原来在这幅图里的改点的入边(就是我们已经存入了这个原节点的入边了,但是,它却构成了环,说明不是我想要的解),所以,新边的权值就是原权值减去终点节点的最小入边。然后,节点数就会变少了,我们就可以继续在这样子优化下去了。直到上面说到的没有再构成环的时候,就说明是解了。
然后呢,我这挂一道Ice_cream’s world II HDU--2121的解题报告,带上完整的注释说明:
#include <iostream> #include <cstdio> #include <cmath> #include <string> #include <cstring> #include <algorithm> #include <limits> #include <vector> #include <stack> #include <queue> #include <set> #include <map> #define lowbit(x) ( x&(-x) ) #define pi 3.141592653589793 #define e 2.718281828459045 #define INF 0x3f3f3f3f using namespace std; typedef unsigned long long ull; typedef long long ll; const int maxN = 1005; int N, M; ll sum; struct Eddge //存边 {int u, v;ll val;Eddge(int a=0, int b=0, ll c=0):u(a), v(b), val(c) {} }edge[maxN*maxN]; int pre[maxN], id[maxN], vis[maxN], pos; ll in[maxN]; //最小入边权,pre[]为其前面的点(该边的起点) ll Dir_MST(int root, int V, int E) //root是此时的根节点,我们最初的时候将0(万能节点作为根节点进入),V是点的个数(包括之后要收缩之后点的剩余个数),E是边的条数(不会改变) {ll ans = 0;while(true) //如果还是可行的话 {for(int i=0; i<V; i++) in[i] = INF; //给予每个点进行初始化/* (1)、最短弧集合E0 */for(int i=1; i<=E; i++) //通过这么多条单向边,确定的是每个点的指向边的最小权值 {int u = edge[i].u, v = edge[i].v;if(edge[i].val < in[v] && u!=v) //顶点v有更小的入边,记录下来 更新操作,u!=v是为了确保缩点之后,我们的环将会变成点的形式 {pre[v] = u; //节点u指向vin[v] = edge[i].val; //最小入边if(u == root) pos = i; //这个点就是实际的起点 }}/* (2)、检查E0 */for(int i=0; i<V; i++) //判断是否存在最小树形图 {if(i == root) continue; //是根节点,不管if(in[i] == INF) return -1; //除了根节点以外,有点没有入边,则根本无法抵达它,说明是独立的点,一定不能构成树形图 }/* (3)、收缩图中的有向环 */int cnt = 0; //接下来要去求环,用以记录环的个数 找环开始!memset(id, -1, sizeof(id));memset(vis, -1, sizeof(vis));in[root] = 0;for(int i=0; i<V; i++) //标记每个环 {ans += in[i]; //加入每个点的入边(既然是最小入边,所以肯定符合最小树形图的思想)int v = i; //v一开始先从第i个节点进去while(vis[v] != i && id[v] == -1 && v != root) //退出的条件有“形成了一个环,即vis回归”、“到了一个环,此时就不要管了,因为那边已经建好环了”、“到了根节点,就是条链,不用管了” {vis[v] = i;v = pre[v];}if(v != root && id[v] == -1) //如果v是root就说明是返回到了根节点,是条链,没环;又或者,它已经是进入了对应环的编号了,不需要再跑一趟了 {for(int u=pre[v]; u!=v; u=pre[u]) //跑这一圈的环 {id[u] = cnt; //标记点u是第几个环 }id[v] = cnt++; //如果再遇到,就是下个点了 }}if(cnt == 0) return ans; //无环的情况,就说明已经取到了最优解,直接返回,或者说是环已经收缩到没有环的情况了for(int i=0; i<V; i++) if(id[i] == -1) id[i] = cnt++; //这些点是环外的点,是链上的点,单独再给他们赋值for(int i=1; i<=E; i++) //准备开始建立新图 缩点,重新标记 {int u = edge[i].u, v = edge[i].v;edge[i].u = id[u]; edge[i].v = id[v]; //建立新图,以新的点进入if(id[u] != id[v]) edge[i].val -= in[v]; //为了不改变原来的式子,使得展开后还是原来的式子 }V = cnt; //之后的点的数目root = id[root]; //新的根节点的序号,因为id[]的改变,所以根节点的序号也改变了 }return ans; } int main() {while(scanf("%d%d", &N, &M)!=EOF){sum = 0;for(int i=1; i<=M; i++){scanf("%d%d%lld", &edge[i].u, &edge[i].v, &edge[i].val);edge[i].u++; edge[i].v++; //把‘0’号节点空出来,用以做万能节点,留作之后用sum += edge[i].val;}sum++; //一定要把sum给扩大,这就意味着,除去万能节点以外的点锁构成的图的权值和得在(sum-1)之内(包含)for(int i=M+1; i<=M+N; i++) //这就是万能节点了,就是从0这号万能节点有通往所有其他节点的路,而我们最后的最小树形图就是从这个万能节点出发所能到达的整幅图 {edge[i] = Eddge(0, i-M, sum); //对于所有的N个其他节点都要建有向边} //此时N+1为总的节点数目,M+N为总的边数ll ans = Dir_MST(0, N + 1, M+N); //ans代表以超级节点0为根的最小树形图的总权值if(ans == -1 || ans - sum >= sum) printf("impossible\n"); //从万能节点的出度只能是1,所以最后的和必须是小于sum的,而万能节点的出度就由“ans - sum >= sum”保证else printf("%lld %d\n", ans - sum, pos - M - 1); //pos-M得到的是1~N的情况,所以“-1”的目的就在于这里printf("\n");}return 0; }
转载于:https://www.cnblogs.com/guanwen769aaaa/p/11295219.html
【转】【最小树形图】有向图的最小生成树【朱刘算法】相关推荐
- POJ3164 最小树形图 有向图的最小生成树 模板题 朱刘算法 朱永津-刘振宏算法
Command Network Time Limit: 1000MS Memory Limit: 131072K Total Submissions: 12833 Accepted: 3717 ...
- [POJ 3164]Command Network(最小树形图,朱刘算法)
文章目录 title solution code title solution 读完翻译后,很明显就是个朱刘算法的板子题 最小树形图,就是给出一个带权有向图 从中指定一个特殊的结点 root 求一棵以 ...
- 最小树形图——朱刘算法
洛咕博客地址:−>ClickHere<−->Click Here<-−>ClickHere<−,求捧场 最近想找最小生成树的题做,奈何难度有限,点进的蓝题紫题都和& ...
- POJ-3164 Command Network (朱刘算法)
这是一道最小树形图的模板题 朱刘算法开始时的确不是太好理解,在网上看了好多文章才差不多理解. 在这里说一点,缩点时,如果弧(u,v)的v点在一个环中,这个环形成的缩点在新图中的编号是k,那么新图中(u ...
- poj3164(最小树形图朱刘算法模板)
题目链接:http://poj.org/problem?id=3164 题意:第一行为n, m,接下来n行为n个点的二维坐标, 再接下来m行每行输入两个数u, v,表点u到点v是单向可达的,求这个有向 ...
- 最小树形图 之 朱刘算法【模板】
定义:一个有向图,存在从某个点为根的,可以到达所有点的一个最小生成树,则它就是最小树形图. 朱刘算法实现过程: [在选出入边集后(看步骤1),若有向图中不存在有向环,说明该图就是最小树形图] 1,选入 ...
- 朱刘算法 有向图的最小生成树
朱刘算法 有向图的类Prim算法,找有向图的最小生成树 最小树形图 树形图: 无有向环 除了根节点外,每个点入度为1 以某个点为根的一棵有向树,其边权之和为图中所有树形图中是最小的称为最小树形图. 朱 ...
- POj 3164 Command Network最小树形图 模板题 朱刘算法
Command Network After a long lasting war on words, a war on arms finally breaks out between littleke ...
- 生成树最小树形图 -- 朱刘算法详解
本文借鉴的博文: zephyr_pro dalao的blog 朱刘算法引入: (把一道最小树形图当作最小生成树来做了,wa了后以为是bug像个sb一样d了半天) 最小树形图和最小生成树都是要求总权值最 ...
- 最小树形图(朱刘算法)模板
最小树形图:有向图,求以某个确定的点为根的外向最小生成树. 最小树形图朱刘算法:https://www.luogu.com.cn/blog/i207M/shu-xing-tu-shu-liu-suan ...
最新文章
- c++输出lpbyte类型_变量类型摸不清脉络?用typeid()试试,用一次就上瘾
- Spring MVC HelloWorld入门及运行机制 (一)
- Asp.NET的DESAES加密算法(转载)
- ef core code first from exist db
- 【linux环境sqlplus登录oracle问题: ORA-12162 ORA-12545】
- 20年中国人均GDP排名变化
- BiNGO的GO分析
- 优化算法 - 遗传算法
- tweenMax代码未定义问题
- 屏幕的单位如何计算机,如何查看您的计算机显示器有多少英寸
- 河南最新道路货物运输驾驶员考试真题及答案解析
- Thinkphp资源源码付费下载站网站源码
- gcc命令行选项说明
- NLP逻辑回归模型(LR)实现分类问题实例详解
- 一年级古诗风语文知识心田花开汇总
- Codeforces Round #649 D. Ehab‘s Last Corollary 【思维,二分图,环】
- 大连美女仿生机器人火了,网友:人形电脑东北银
- 基于vs实现的socket—udp图片传送实例详解
- 网易为什么成门户唯一常青树?从几个产品说起
- 2018年贺岁档电影票房大数据报告!国产电影的黄金时代已经到来?
热门文章
- VG SketchPad编辑器——可嵌入的jQuery插件
- (五)从头开始构建风格迁移CycleGAN
- CKEditor 4.14 发布,支持复制粘贴 LibreOffice 文档
- 高级Blazor:从Edge共享程序集和调试
- C#中的Nutshell函数式编程
- Microsoft 宣布 Visual Studio 2019 发布日期
- php更改tittle,phpcms V9修改默认title标签
- 通过js滚轮滚动时调用动画_WOW.js在页面滚动时展现动感的元素动画效果
- Java内部类手机专卖店_Java:内部类
- python和c的语法区别_python与c语言的语法有哪些不一样的