soj3427: Dark roads_最小生成树Kruskal

来源:互联网 发布:服装数据分析软件 编辑:程序博客网 时间:2024/06/09 18:00

soj3427: Dark road

http://acm.scu.edu.cn/soj/problem.action?id=3427

上周五太忙没做,本周多做一道,唉

题目简介:就是。。最小生成树的权值和比整棵树权值和少了多少。

因为本题数值太大,所以没法prim,就重新复习了一下kruskal最小生成树的方法,原理就是并查集,虽然当时学就是这样= =,不过不用并查集应该也可以,就是复杂了呗,自己实现一下去吧。

先讲并查集,就是看两棵树,找根,如果他们的根不同,那就没有相连,就不是一棵树的,这个时候就可以把一个的根当做另一个的根,这俩树就连在一起啦。


哎呦天,这个图我画的有点大,就是举例嘛,假设上图是我们找到的两个树,find(B)是否=find(F),查找B,F的根,AE并不相等,所以可以连起来,不会出现回路。

所以并查集就是:

int find(int a){    if(pre[a] == a)        return a;    else        return pre[a] = find(pre[a]);             //注意这句}for(int i = 0;i <= n; i++)    pre[i] = i;for(int i = 1;i <= m; i++){    int a = find(edge[i].x);    int b = find(edge[i].y);    if(a != b)        pre[a] = b;}


大概就是上面简短的部分代码

然后Kruskal这道题就结束了:

#include<cstdio>#include<algorithm>using namespace std;#define MAX 200010int pre[MAX];struct map{    int x,y,len;}edge[MAX];bool cmp(map a, map b){    return a.len < b.len;}int find(int a){    if(pre[a] == a)        return a;    else        return pre[a] = find(pre[a]);}void Kruskal(int m,int n,int money){    int res = 0;    for(int i = 0;i <= m; i++)        pre[i] = i;    for(int i = 1;i <= n; i++)    {        int a = find(edge[i].x);        int b = find(edge[i].y);        if(a != b)        {            pre[a] = b;            res += edge[i].len;        }    }    printf("%d\n",money-res);}int main(){    int m,n;    while(~scanf("%d%d",&m,&n))    {        int money = 0;        if(m==0 && n==0)            break;        for(int i = 1;i <= n; i++)        {            scanf("%d%d%d",&edge[i].x,&edge[i].y,&edge[i].len);            money += edge[i].len;        }        sort(edge+1,edge+1+n,cmp);        Kruskal(m,n,money);    }    return 0;}




原创粉丝点击