hdu 1863 最小生成树

来源:互联网 发布:ubuntu flash 安装 编辑:程序博客网 时间:2024/06/06 00:18
省政府“畅通工程”的目标是使全省任何两个村庄间都可以实现公路交通(但不一定有直接的公路相连,只要能间接通过公路可达即可)。经过调查评估,得到的统计表中列出了有可能建设公路的若干条道路的成本。现请你编写程序,计算出全省畅通需要的最低成本。

Input

测试输入包含若干测试用例。每个测试用例的第1行给出评估的道路条数 N、村庄数目M ( < 100 );随后的 N 
行对应村庄间道路的成本,每行给出一对正整数,分别是两个村庄的编号,以及此两村庄间道路的成本(也是正整数)。为简单起见,村庄从1到M编号。当N为0时,全部输入结束,相应的结果不要输出。

Output

对每个测试用例,在1行里输出全省畅通需要的最低成本。若统计数据不足以保证畅通,则输出“?”。

Sample Input

3 31 2 11 3 22 3 41 32 3 20 100

Sample Output

3

?

//并查集加快排 Kruskal算法#include<stdio.h>#include<algorithm>using namespace std;int f[110],n,m,sum;struct p{    int u;    int v;    int w;} e[110];bool comp(p n1,p n2){    return n1.w<n2.w;}int getf(int v){    if(f[v]==v)        return v;    else    {        f[v]=getf(f[v]);        return f[v];    }}int merge(int x,int y){    int t1,t2;    t1=getf(x);    t2=getf(y);    if(t1!=t2) //判断两个点是否在同一集合,即是否连通    {        f[t2]=t1;         return 1; //不连通返回1    }    return 0; //连通返回0}int main(){    int i;    while(~scanf("%d%d",&n,&m))    {        int flag=0;        int sum=0,num=0;        if(n==0)            break;        for(i=1; i<=m; i++) //初始化            f[i]=i;        for(i=1; i<=n; i++)            scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].w);        sort(e+1,e+n+1,comp);  //按照权值从小到大排序        for(i=0; i<=n; i++)        {            if(merge(e[i].u,e[i].v))            {                num++;                sum+=e[i].w; //尚未连通则选择这条边连通            }            if(num==m-1) //直到选用了m-1条边,跳出循环            {                flag=1;                break;            }        }        if(flag==1)            printf("%d\n",sum);        else                  //边数不够,无法连通            printf("?\n");    }    return 0;}

//prim算法#include<stdio.h>#include<string.h>int main(){    int n,m,i,j,k,t1,t2,t3,min;    int e[101][101],dis[101],book[101];    int inf=999999999;    while(~scanf("%d%d",&n,&m))    {        int flag=0;        if(n==0)            break;        int count=0,sum=0;        memset(book,0,sizeof(book));        for(i=1; i<=m; i++)            for(j=1; j<=m; j++) //初始化                e[i][j]=inf;        for(i=1; i<=n; i++)        {            scanf("%d%d%d",&t1,&t2,&t3);            if(e[t1][t2]>t3)            {                e[t1][t2]=t3;                e[t2][t1]=t3;            }        }        for(i=1; i<=m; i++)            dis[i]=e[1][i]; //1号顶点到各顶点的初始距离,生成树当前只有1号顶点        book[1]=1;        count++;        while(count<m) //找到m个点        {            min=inf;            for(i=1; i<=m; i++)            {                if(book[i]==0&&dis[i]<min) //找到当前最短的路                {                    min=dis[i];                    j=i;                }            }            if(min==inf)            {                flag=1;  //如果最短路径等于无穷大,则说明路不能连通                break;            }            book[j]=1;            count++;            sum+=dis[j];            for(k=1; k<=m; k++)            {                if(book[k]==0&&dis[k]>e[j][k]) //更新路径,找到可以连通的最短距离                    dis[k]=e[j][k];            }        }        if(flag==0)            printf("%d\n",sum);        else            printf("?\n");    }    return 0;}


0 0
原创粉丝点击