还是畅通工程
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 12633 Accepted Submission(s): 5811
Problem Description
某省调查乡村交通状况,得到的统计表中列出了任意两村庄间的距离。省政府“畅通工程”的目标是使全省任何两个村庄间都可以实现公路交通(但不一定有直接的公路相连,只要能间接通过公路可达即可),并要求铺设的公路总长度为最小。请计算最小的公路总长度。
Input
测试输入包含若干测试用例。每个测试用例的第1行给出村庄数目N ( < 100 );随后的N(N-1)/2行对应村庄间的距离,每行给出一对正整数,分别是两个村庄的编号,以及此两村庄间的距离。为简单起见,村庄从1到N编号。
当N为0时,输入结束,该用例不被处理。
当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
分析:
模板使用
方法一:prim算法 邻接矩阵实现O(n^2)。
s[] 表示已经包含的顶点;lowcost[] 表示剩下的顶点到集合 s[] 中的权值。
如果不是所以的顶点两两都有直接通路,要对map[][]进行初始化
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
1 #include<iostream> 2 #include<cstring> 3 #define N 110 4 using namespace std; 5 6 int map[N][N],lowcost[N]; 7 bool s[N]; 8 9 int prim(int n) 10 { 11 int i,j,k,ans=0,min; 12 s[1]=true; 13 for(i=2;i<=n;i++) 14 { 15 lowcost[i]=map[1][i]; 16 s[i]=false; 17 } 18 for(i=1;i<n;i++) 19 { 20 min=200000000;k=0; 21 for(j=2;j<=n;j++) 22 { 23 if(min>lowcost[j]&&!s[j]) 24 { 25 min=lowcost[j]; 26 k=j; 27 } 28 } 29 ans+=min;s[k]=true; 30 for(j=2;j<=n;j++) 31 { 32 if(map[k][j]<lowcost[j]&&!s[j]) 33 lowcost[j]=map[k][j]; 34 } 35 } 36 return ans; 37 } 38 39 int main() 40 { 41 int i,n,u,v,w; 42 while(cin>>n&&n) 43 { 44 for(i=1;i<=n*(n-1)/2;i++) 45 { 46 cin>>u>>v>>w; 47 map[v][u]=map[u][v]=w; 48 } 49 int ans=prim(n); 50 cout<<ans<<endl; 51 } 52 return 0; 53 }
方法二:Kruskal算法 O(e*loge)排序的复杂度。并查集中的查找可以优化。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
1 #include<iostream> 2 #include<algorithm> 3 #define N 110 4 using namespace std; 5 6 struct node{int u,v,w;}edge[N*N]; 7 int parent[N]; 8 9 bool cmp(node a,node b) 10 { 11 if(a.w<=b.w) return true; 12 return false; 13 } 14 15 int find(int a)//判断是否相交 16 { 17 if(a!=parent[a]) 18 return find(parent[a]); 19 else return a; 20 } 21 22 int kruskal(int n,int m) 23 { 24 int i,x,y,ans=0; 25 for(i=1;i<=n;i++) parent[i]=i; 26 sort(edge,edge+m,cmp); 27 for(i=0;i<m;i++)//循环可以减少只要已经有n-1条边就 return ; 28 { 29 x=edge[i].u; 30 y=edge[i].v; 31 x=find(x);//这里可以优化 32 y=find(y); 33 if(x!=y) 34 { 35 parent[y]=x;//合并 36 ans+=edge[i].w; 37 } 38 } 39 return ans; 40 } 41 42 int main() 43 { 44 int i,x,y,z,m,n,ans; 45 while(cin>>n&&n) 46 { 47 m=0; 48 for(i=1;i<=n*(n-1)/2;i++) 49 { 50 cin>>x>>y>>z; 51 edge[m].u=x; 52 edge[m].v=y; 53 edge[m].w=z; 54 m++; 55 } 56 ans=kruskal(n,m); 57 cout<<ans<<endl; 58 } 59 return 0; 60 }