poj 3164 朱刘算法(最小树形图)

题意:裸题。所谓最小树形图:给定一个带权有向图和一个固定结点n,求从n出发能到达所有点的最小权生成树。

思路:朱刘算法,最坏情况复杂度位O(VE)。后有优化算法降低了复杂度。

算法步骤如下:(本文不再证明,参考下面给出的我自己画的一个图即可理解)
1.判断图的连通性,若不连通直接无解,否则一定有解。
2.为除了根节点以外的所有点选择一个权值最小的入边,假设用pre数组记录前驱,f数组记录选择的边长,记所选边权和为temp。
3.(可利用并查集)判断选择的的边是否构成环,若没有则直接ans+=temp并输出ans,若有,则进行下一步操作。
4.对该环实施缩点操作,设该环上有点V1,V2……Vi……Vn,缩成的点为node ,对于所有不在环中的点P进行如下更改:
(1) 点P到node的距离为min{a[p,Vi]-f[Vi]} (a为边集数组)
(2)点node到p的距离为min{a[Vi,p]}
操作(1)的理解:先假设环上所有边均选上,若下次选择某一条边进入该环,则可以断开进入点与进入点的前驱之间的边,即断开F[进入点],所以等效为直接把a[p,node]赋值为min{a[p,Vi]-f[Vi]}。
特别提醒:本题有自环,可以提前删掉,因为它没有用。

#include 
#include 
#include 
#include 
using namespace std;
#define clr(s,t) memset(s,t,sizeof(s));
#define INF 0x3fffffff
#define N 105
#define M 10005
struct point{
    double x,y;
}p[N];
struct edge{
    int x,y,next;
    double w;
}e[M];
int first[N],top,n,m,used[N],f[N],pre[N],root;
double in[N];
double dist(point a,point b){
    return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
void add(int x,int y,double w){
    e[top].x = x;
    e[top].y = y;
    e[top].w = w;
    e[top].next = first[x];
    first[x] = top++;
}
double zhu_liu(){
    int i,num,a,b;
    double res = 0;
    root = 1;
    while(1){
        for(i = 1;i<=n;i++)
            in[i] = INF;
        for(i = 0;i


你可能感兴趣的:(图论——MST及相关)