zoukankan      html  css  js  c++  java
  • HDU 1233-还是畅通工程(经典最小生成树)

    还是畅通工程
    Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
    Total Submission(s): 74407 Accepted Submission(s): 33605

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

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

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

    Sample Input
    3
    1 2 1
    1 3 2
    2 3 4
    4
    1 2 1
    1 3 4
    1 4 1
    2 3 3
    2 4 2
    3 4 5
    0

    Sample Output
    3
    5

    题目大意:给定n个村庄和m条路,求可以连通所有村庄的路的最小值。
    解题思路:这道是HDU上一道很经典的最小生成树的模板题,可以用Kruskal算法和Prim算法的模板,值得注意的是,Kruskal算法需要并查集基础,Prim算法要有dijkstra最短路算法基础,因为原理是差不多的。贴两个AC代码:
    Kruskal算法:

    #include <cstdio>
    #include <iostream>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    const int _max=1e4;
    struct edge{int u,v,w;};
    int f[105];
    int n,r,cnt,sum;
    struct edge e[_max];
    int main()
    {
    	bool marge(int,int);
    	bool cmp(edge,edge);
    	while(scanf("%d",&n))
    	{
    	    if(n==0)
    		  break;
    		cnt=sum=0;
    		memset(e,0,sizeof(e));
    		r=n*(n-1)/2;
    		for(int i=1;i<=r;i++)
    		  cin>>e[i].u>>e[i].v>>e[i].w;
    		sort(e+1,e+r+1,cmp);
    		for(int i=1;i<=n;i++)
    		  f[i]=i;
    		for(int i=1;i<=r;i++)
    		{
    			if(marge(e[i].u,e[i].v))
    			{
    				cnt++;
    				sum+=e[i].w;
    			}
    			if(cnt==n-1)
    			  break;
    		}
    		printf("%d
    ",sum);
    	}
    	return 0;
    }
    int getf(int v)
    {
    	if(f[v]==v)
    	  return v;
    	else
    	{
    		f[v]=getf(f[v]);
    		return f[v];
    	}
    }
    bool marge(int u,int v)
    {
    	int t1,t2;
    	t1=getf(u);
    	t2=getf(v);
    	if(t1!=t2)
    	{
    		f[t2]=t1;
    		return true;
    	}
    	return false;
    }
    bool cmp(edge u,edge v)
    {
    	return u.w<v.w;
    }
    

    Prim算法:

    #include <cstdio>
    #include <iostream>
    #include <algorithm>
    #include <cstring>
    #define mian main
    using namespace std;
    const int N=105;
    int map[N][N],book[N],dis[N];
    const int inf=0x3f3f3f3f;
    int n;
    int main()
    {
    	ios::sync_with_stdio(false);
    	void prim();
    	while(cin>>n&&n)
    	{
    		for(int i=1;i<=n;i++)
    		  for(int j=0;j<=i;j++)
    		    if(i==j)
    		      map[i][j]=0;
    		    else
    			  map[i][j]=map[j][i]=inf;  
    		int m=n*(n-1)/2;
    		for(int i=1;i<=m;i++)
    		{
    			int a,b,c;
    			cin>>a>>b>>c;
    			map[a][b]=map[b][a]=c;
    		}
    		memset(dis,0,sizeof(dis));
    		memset(book,0,sizeof(book));
    		for(int i=1;i<=n;i++)
    		  dis[i]=map[1][i];
    		book[1]=1;
    		prim();
    		int sum=0;
    		for(int i=1;i<=n;i++)
    		  sum+=dis[i];
    		cout<<sum<<endl;
    	}
    }
    void prim()
    {
    	int cnt=1;
    	int i,j,k;
    	while(cnt<n)
    	{
    		int min=inf;
    		for(i=1;i<=n;i++)
    		{
    			if(!book[i]&&dis[i]<min)
    			{
    				min=dis[i];
    				j=i;
    			}
    		}
    		book[j]=1;
    		cnt++;
    		for(k=1;k<=n;k++)
    		{
    			if(!book[k]&&dis[k]>map[j][k])
    			  dis[k]=map[j][k];
    		}
    	}
    }
    
  • 相关阅读:
    关于postman使用上发现的一点问题
    关于异步的处理方法
    关于console.log() 打印得引用类型得数据得相关问题
    使用electron将单页面vue webapp 打包成 PC端应用
    当后台只接受字符串得时候,在传输复杂得数据得时候会发生得问题
    默认事件
    事件冒泡
    offsetWidth clientWidth scrollWidth 三者之间的区别和联系
    事件获取目标 currentTarget target srcElement三者之间的区别和联系
    不支持模块化规范的插件可以使用import 导入的原因
  • 原文地址:https://www.cnblogs.com/Hayasaka/p/14294311.html
Copyright © 2011-2022 走看看