Kruskal & Prim 最小生成树HDU1863 畅通工程

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1863

题意:求构成一个连通图的最小代价,一看就是最小生成树。

思路:最小生成树版题。

想用use数组表示两个点是否用过,后来发现这样行不通,因为会忽略链接两个连通子图的边。

源码:

Kruskal:

#include <cstdio>

#include <cmath>

#include <cstring>

#include <string>

#include <iostream>

#include <algorithm>

#include <queue>

#include <vector>

using namespace std;

int const MAXN = 100+2;

int pa[MAXN],use[MAXN],ans,n,m,dot;

struct edge

{

    int s,e,val;

    void init(int a,int b,int c)

    {

        s = a; e = b; val = c;

    }

}d[MAXN*MAXN];

bool cmp(edge a,edge b)

{

    return a.val<b.val;

}

int fi(int a)

{

    if(a!=pa[a]) return fi(pa[a]);

    return a;

}

void init()

{

    for(int i=1; i<=m; i++) pa[i] = i;

    memset(use,0,sizeof(use));

    int s,e,val;

    for(int i=0; i<n; i++){

        scanf("%d%d%d",&s,&e,&val);

        d[i].init(s,e,val);

    }

    sort(d,d+n,cmp);

    ans = 0;

}

void Kruskal()

{

    dot = 1;

    for(int i=0; i<n; i++){

        int x = fi(d[i].s);

        int y = fi(d[i].e);

        if(x!=y){

            dot++;

            pa[x] = y;

            ans+=d[i].val;

        }

    }

}

void solve()

{

    if(dot!=m)    printf("?\n");

    else printf("%d\n",ans);

}

int main()

{

    while(scanf("%d%d",&n,&m)!=EOF && n){

        init();

        Kruskal();

        solve();

    }

    return 0;

}

Prim

#include <cstdio>

#include <cstring>

#include <cmath>

#include <algorithm>

#include <iostream>

#include <queue>

using namespace std;

int const MAXN = 100+5;

int edge[MAXN][MAXN],use[MAXN],tot,ans,n,m;

struct D

{

    int mark,val;

}low[MAXN];

void init()

{

    memset(use,0,sizeof(use));

    memset(edge,-1,sizeof(edge));

    int s,e,val;

    while(n--){

        scanf("%d%d%d",&s,&e,&val);

        edge[e][s] = edge[s][e] = val;

    }

    tot = 1;

    ans = 0;

}

int fi()

{

    int flag = 1;

    int pos = 1;

    for(int i=1; i<=m; i++)

    {

        if(use[i]==0 && low[i].val!=-1 && (low[i].val<=low[pos].val || low[pos].val==-1)){

            flag = 0;

            pos = i;

        }

    }

    if(flag)    return -1;

    else    return pos;

}

void Prim()

{

    use[1] = 1;

    int pos = 1;

    for(int i=1; i<=m; i++){///初始化

        low[i].mark = 1;

        low[i].val = edge[1][i];

    }

    pos = fi();

    tot++;

    ans += low[pos].val;

    use[pos] = 1;

    while(1){

        for(int j=1; j<=m; j++){

            if(edge[pos][j]!=-1 && use[j]==0 && ((edge[pos][j]<low[j].val) || low[j].val==-1)){

                low[j].mark = pos;

                low[j].val = edge[pos][j];

            }

        }

        pos = fi();

        if(pos != -1){

            ans += low[pos].val;

            use[pos] = 1;

            tot++;

        }

        else break;

    }

}

void solve()

{

    if(tot==m)  printf("%d\n",ans);

    else    printf("?\n");

}

int main()

{

    while(scanf("%d%d",&n,&m)!=EOF && n){

        init();

        Prim();

        solve();

    }

    return 0;

}

 

错误版:

#include <cstdio>

#include <cmath>

#include <cstring>

#include <string>

#include <iostream>

#include <algorithm>

#include <queue>

#include <vector>

using namespace std;

int const MAXN = 100+2;

int pa[MAXN],use[MAXN],ans,n,m,dot;

struct edge

{

    int s,e,val;

    void init(int a,int b,int c)

    {

        s = a; e = b; val = c;

    }

}d[MAXN*MAXN];

bool cmp(edge a,edge b)

{

    return a.val<b.val;

}

int fi(int a)

{

    if(a!=pa[a]) return fi(pa[a]);

    return a;

}

void init()

{

    for(int i=1; i<=m; i++) pa[i] = i;

    memset(use,0,sizeof(use));

    int s,e,val;

    for(int i=0; i<n; i++){

        scanf("%d%d%d",&s,&e,&val);

        d[i].init(s,e,val);

    }

    sort(d,d+n,cmp);

    ans = 0;

}

void Kruskal()

{

//    use[d[0].s] = 1;

//    use[d[0].e] = 1;

//    ans += d[0].val;

//    dot = 1;

    for(int i=0; i<n; i++){

        if(use[d[i].s]==1 && use[d[i].e]==1)

            continue;

        use[d[i].s] = 1;

        use[d[i].e] = 1;

//        int x = fi(d[i].s);

//        int y = fi(d[i].e);

//        printf("i = %d,x = %d,y = %d\n",i,x,y);

//        if(x!=y){

//            dot++;

//            pa[x] = y;

//            ans+=d[i].val;

//        }

        ans += d[i].val;

    }

}

void solve()

{

    int flag = 0;

    for(int i=1; i<=n; i++){

        if(use[i]==0){

            flag = 1; break;

        }

    }

    if(flag)    printf("?\n");

    else    printf("%d\n",ans);

 

}

int main()

{

    while(scanf("%d%d",&n,&m)!=EOF && n){

        init();

        Kruskal();

        solve();

    }

    return 0;

}

 

1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值