HDOJ--1233

来源:互联网 发布:大数据时代什么意思 编辑:程序博客网 时间:2024/06/01 22:16

还是畅通工程

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 40080    Accepted Submission(s): 18228


Problem Description
某省调查乡村交通状况,得到的统计表中列出了任意两村庄间的距离。省政府“畅通工程”的目标是使全省任何两个村庄间都可以实现公路交通(但不一定有直接的公路相连,只要能间接通过公路可达即可),并要求铺设的公路总长度为最小。请计算最小的公路总长度。
 

Input
测试输入包含若干测试用例。每个测试用例的第1行给出村庄数目N ( < 100 );随后的N(N-1)/2行对应村庄间的距离,每行给出一对正整数,分别是两个村庄的编号,以及此两村庄间的距离。为简单起见,村庄从1到N编号。
当N为0时,输入结束,该用例不被处理。
 

Output
对每个测试用例,在1行里输出最小的公路总长度。
 

Sample Input
31 2 11 3 22 3 441 2 11 3 41 4 12 3 32 4 23 4 50
 

Sample Output
35
Hint
Hint
Huge input, scanf is recommended.
#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int inf=0x3f3f3f3f;int map[105][105];int prim(int n){int vis[105]={0},dis[105],ans=0;memset(dis,inf,sizeof(dis));//初始化为无穷大dis[1]=0;//随意选定一个点开始for(int i=1;i<=n;++i)//循环加入n个顶点{int k=-1,tp=inf;for(int j=1;j<=n;++j)//查找距离已连接的部分最近的顶点{if(!vis[j]&&dis[j]<tp){k=j;tp=dis[j];}}vis[k]=1;ans+=tp;//统计和标记 for(int j=1;j<=n;++j)//更新未选中的点和已经连接的部分之间的最短距离 {if(!vis[j]&&map[k][j]<dis[j]){dis[j]=map[k][j];}}}return ans;}int main(){    int n,m,a,b,c;    while(scanf("%d",&n)&&n)    {    memset(map,inf,sizeof(map));        m=n*(n-1)/2;//边的数量         for(int i=0;i<m;i++)        {            scanf("%d%d%d",&a,&b,&c);            map[a][b]=map[b][a]=c;//无向边         }        printf("%d\n",prim(n));    }    return 0;}

//kruscal 算法 #include<stdio.h>#include<string.h>#include<algorithm>using namespace std;int per[105],n;struct node//结构体来保存边{    int a,b;    int dis;}x[5005];bool cmp(node a,node b){    return a.dis<b.dis;}void init()//初始化操作{    for(int i=1;i<=n;++i)    {        per[i]=i;    }}int find(int x)//并查集的查找操作{    int r=x;    while(r!=per[r])    {        r=per[r];    }    int i=x,j;    while(i!=r)    {        j=per[i];        per[i]=r;        i=j;    }    return r;}bool join(int a,int b)//判断某条边是否可以选择{    int x=find(a),y=find(b);    if(x!=y)    {        per[y]=x;        return 1;    }    return 0;}int main(){    int a,b,c,m;    while(scanf("%d",&n),n)    {        init();        m=n*(n-1)/2;        for(int i=0;i<m;++i)        {            scanf("%d%d%d",&a,&b,&c);            x[i].a=a;x[i].b=b;x[i].dis=c;        }        sort(x,x+m,cmp);//对边进行排序        int sum=0,cnt=0;        for(int i=0;cnt<n-1;++i)//依次选择使得所有顶点连通的边        {            if(join(x[i].a,x[i].b))            {                sum+=x[i].dis;                ++cnt;            }        }        printf("%d\n",sum);//输出最小生成树的权值    }    return 0;}

0 0
原创粉丝点击