hdu2122 poj2485 最小生成树

最小生成树的题俩算法,prim和kruskal,分别以以下两题为例(我不会说是在练prim的时候2122用prim死也不A。。)

2122的题意就不说了,很短很直接,用意思相当好懂的kruskal,也就是在保证没有环的前提下一直添入最短的边,所以说,排个序,判个环,连接一下,累加一下就可以啦~

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<algorithm>
#define inf 999999999
using namespace std;
int father[1001];
int find(int x)
{
    if(father[x]==x)return x;
    father[x]=find(father[x]);
    return father[x];
}
struct node
{
    int s,t,c;
}way[10001];

int cmp(node a,node b)
{
    return a.c<b.c;
}
int main()
{
    int n,m;
    int x,y;
    while(scanf("%d%d",&n,&m)!=-1)
    {
        for(int i=0;i<n;i++)
            father[i]=i;
        for(int i=0;i<m;i++)
            scanf("%d%d%d",&way[i].s,&way[i].t,&way[i].c);
        sort(way,way+m,cmp);
        int ans,t;
        t=0;
        ans=0;
        for(int i=0;i<m;i++)
        {
            x=find(way[i].s);
            y=find(way[i].t);
            if(x!=y)
            {
                t++;
                ans+=way[i].c;
                father[x]=y;
            }
        }
        if(t!=n-1)printf("impossible\n");
        else
            printf("%d\n",ans);
        printf("\n");
    }
    return 0;
}

2485是要求已经生成的最小生成树里最大的那条边,设个临时变量,判断一下就好~

这道是用的prim,思想上说比kruskal曲折,不过如果图的边很多,用kruskal有风险,所以嘛,方法什么的,依情况定(虽然我一般都搞不清情况。。)

prim的话呢,就是从一个点开始,先找出与之相连的最短的那条边,这样便找到了第二个点,再以此类推找到后面的点,也就是找边,更新权值的过程,题目要的结果加上个判断,当然一个判定这个节点是否被访问过的visit数组当然不可少。

#include<stdio.h>
#define max 510

int init[max][max],dis[max],n;
bool visit[max];


int prim()
{
    int temp=0,po;
    visit[0]=true;
    for(int i=0;i<n;i++)
        dis[i]=init[0][i];
        //printf("dis%d\n",visit[1]);

    //每轮
    for(int i=1;i<n;i++)
    {
        int min=65550;

        for(int j=0;j<n;j++)
        {
            if(visit[j]==false&&dis[j]<min)
            {

                min=dis[j];
                po=j;
            }
        }
        visit[po]=true;
        if(temp<min)
        {
            temp=min;
           // printf("yes%d\n",temp);
        }

        //更新权值
        for(int k=0;k<n;k++)
        {
            if(visit[k]==false&&dis[k]>init[po][k])
            {
                dis[k]=init[po][k];
                //printf("no");
            }
        }
    }
    return temp;
}

int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d",&n);
        for(int i=0;i<n;i++)
            for(int j=0;j<n;j++)
            {
                scanf("%d",&init[i][j]);
                visit[j]=false;
            }

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





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值