最小生成树(Prime/kruskal)

来源:互联网 发布:手游天龙部3D百度端口 编辑:程序博客网 时间:2024/05/24 03:19

构造最小生成树一般使用贪心策略,每次优先选择边权值最小的边
最小生成树的边数==点数-1
例子: HDOJ 1863 畅通工程
kruskal算法(用到并查集的知识):按边权值的大小从小到大排序,从边集中选取一条权值最小的边,若该边的两个顶点分属不同的树 ,则将其加入子图,也就是这两个顶点分别所在的 两棵树合成一棵树(通过并查集);反之,若该边的两个顶点已落在同一棵树上,则不可取,而应该取下一条权值最小的边再试之。依次类推,直至森林只有一棵树


while (scanf("%d %d", &n, &m) != EOF, n)    {        num = 0;        sum = 0;        memset(father, 0, sizeof(father));        for (i = 0; i < n; i++)        {            scanf("%d %d %d", &a, &b, &c);            map[i].x = a;            map[i].y = b;            map[i].p = c;//边权值            if (father[a] == 0)                father[a] = a;            if (father[b] == 0)                father[b] = b;        }        sort(map, map + n,cmp);//将边排序        for (i = 0; i < n; i++)        {            if (mix(map[i].x, map[i].y))//通过并查集将边连起来构成最小生成树            {                num++;//记录边的数目                sum += map[i].p;            }        }

Prime算法(与dijkstra算法相似):大部分操作和dijkstra一样,只是松弛操作时略有不同


int prime(int cur){    int index;    int sum = 0;    memset(visit, false, sizeof(visit));    visit[cur] = true;    for(int i = 0; i < n; i ++){        dist[i] = tree[cur][i];    //保存各点到cur的初始距离    }    for(int i = 1; i <= n; i ++)    {        int min = INF;        {            if(!visit[j] && dist[j] < min)            {                min = dist[j];//遍历所有点,找到离源点距离最小的点                index = j;  //记录该点的数组下标              }            }        visit[index] = true;//标记已访问        sum += min;        for(int j = 0; j < n; j ++)        {            if(!visit[j] && dist[j] > tree[index][j])            {                         dist[j] = tree[index][j];//略与dijkstra不同,此时dist数组保存的是刚刚加入的点                                           //和已经加入的点                                         //到其他点的最短距离                              }            }        }     return sum;    }
0 0
原创粉丝点击