对于有向图的最小生成树 , 也叫做最小树形图 。 最小树形图的第一个算法是1965年朱永津和刘振宏提出的复杂度为O(VE)的算法。 值得我们骄傲啊 。
下面来分享这个算法 。
1、求最小树形图之前一定要确定根 , 确定根之后再去验证是否存在树形图(这个很简单 , 就是从根节点能不能到其他点) 。
2、如果存在树形图 , 然后再消掉自环 , 因为对于最小树形图 , 是肯定不能存在自环的(还有原因后面会讲到) 。
3、前面是两个预处理 。 求每个节点入边的最小值(除根节点) , 然后再把(求每个节点入边的最小值的边)这些边单独拿出来 , 看它们之间是否存在环(这就是为什么要先消除自环), 如果不存在那么这就是最小树形图。
4、如果存在环 , 那么就开始消环 , 用一个结点来取代这个环中的所有点 , 然后再把其放到原图中 , 构成新的图 , 并且图中的边的权值要改变为:grap[i].c(原边的权值) -= min_cost[v](该边出点的最小入边值); , 然后再回到步骤3 , 重复操作 , 就能得到最小树形图。
下面是最小树形图的构造图示:
代码:
邻接表法:
#include
#include
#include
#include
using namespace std;
const int MAXN = 1000;
struct node
{
int from , to , dist;
node(int from , int to , int dist)
//
c++中的类应用
{
this->from = from ;
this->to = to;
this->dist = dist;
}
};
vectoredge;
int pre[MAXN] , min_dist[MAXN] ; //分别记录每个节点入边的最小值和入边另外一个点
int n , m , root , ret;
void init()
{
edge.clear();
root = 1;
}
bool solve()
{
ret = 0;
//
记录最小总权值
while(1)
{
int i;
for(i = 1; i <= n; i++)
min_dist[i] = 1000000;
for(i = 0 ; i < edge.size(); i++)
//
求每个节点的最小入边 ,
{
int u = edge[i].from , v = edge[i].to;
if(edge[i].dist < min_dist[v] && v != u)
//
把自环除开
{
min_dist[v] = edge[i].dist;
//cout<<min_dist[v
下面来分享这个算法 。
1、求最小树形图之前一定要确定根 , 确定根之后再去验证是否存在树形图(这个很简单 , 就是从根节点能不能到其他点) 。
2、如果存在树形图 , 然后再消掉自环 , 因为对于最小树形图 , 是肯定不能存在自环的(还有原因后面会讲到) 。
3、前面是两个预处理 。 求每个节点入边的最小值(除根节点) , 然后再把(求每个节点入边的最小值的边)这些边单独拿出来 , 看它们之间是否存在环(这就是为什么要先消除自环), 如果不存在那么这就是最小树形图。
4、如果存在环 , 那么就开始消环 , 用一个结点来取代这个环中的所有点 , 然后再把其放到原图中 , 构成新的图 , 并且图中的边的权值要改变为:grap[i].c(原边的权值) -= min_cost[v](该边出点的最小入边值); , 然后再回到步骤3 , 重复操作 , 就能得到最小树形图。
下面是最小树形图的构造图示:
代码:
邻接表法:
#include
#include
#include
#include
using namespace std;
const int MAXN = 1000;
struct node
{
};
vectoredge;
int pre[MAXN] , min_dist[MAXN] ;
int n , m , root , ret;
void init()
{
}
bool solve()
{