【最小生成树】(一) kruskal求解 POJ1287

题目

Networking

算法

kruskal伪码如下:

//kruskal伪码描述
void kruskal()
{
    MST = { };
    while( MST中不到 |V|-1 条边 && E中还有边 ){
        //找到MST         //有孤立节点
        从E中找到权值最小的边e(v,w); //最小堆或排序
        将 e(v,w) 从E中删除; 
        if( e(v,w) 不在   MST 中构成回路 )//并查集(※这里的构成回路值得是“无向图的回路”)
            将e(v,w)加入MST;
        else
            彻底无视e(v,w);
    }
    if(MST中不到|V|-1条边)
        Error;
}

找最小边的过程我简单的用的暴力。

思路

  • 用结构Edge存下所有边(存下起止点,权值)。
  • 按权值将边排序。
  • 用并查集判断是否构成回路。(使用的“并查集类”来自@Sequix 学长,非常炫酷,拜谢)
  • 计算求得最小生成树的总权值。

代码

#include 
#include 
#include 

using namespace std;

class unionFind{//炫酷的并查集类
private:
    int par[100];
public:
    unionFind(int n)
    {
        for(int i=1;i<=n;i++)//※此处出错:点是从1开始的!!
            par[i] = i;
    }

    int getPar(int a)
    {
        if(par[a] != a){
            par[a] = getPar(par[a]);
        }
       return par[a];
    }

    void merge(int x,int y)
    {
        par[getPar(x)] = getPar(y);
        //为了dp,相当于 getPar(y); par[y] = getPar(x);
        //体会一下:如果equal 一定在merge前进行,这里可以单纯赋值par[y] = par[x];
    }

    bool equal(int x,int y)
    {
        return getPar(x) == getPar(y);//这函数本身就有dp
    }
};

struct Edge{
    int from,to,cost;

    Edge(int f=0,int t=0,int c=0):from(f),to(t),cost(c){}///结构里不会自动生成默认构造函数,所以这里赋上初值是最方便的

    bool operator < (const Edge &e)const {return cost < e.cost;}
}edges[3000];//50*50

int V,E;//vertex edge

int kruskal()
{
    int res = 0;
    unionFind uf(V);

    sort(edges,edges+E);
    for(int i=0;iif(!uf.equal(e.from,e.to)){//不形成回路(无向图的回路)

            uf.merge(e.from,e.to);
            res += e.cost;
        }
    }

    return res;
}

int main()
{

    int u,v,c;

    while(scanf("%d",&V)&&V){
            scanf("%d",&E);
        for(int i=0;iscanf("%d%d%d",&u,&v,&c);
            edges[i] = Edge(u,v,c);//save the graph in edges-->因为这样的结构易于操作
        }

        printf("%d\n",kruskal());
    }
    return 0;
}

你可能感兴趣的:(#ACM刷题笔记,图论)