PTA 7-50 畅通工程之局部最小花费问题(最小生成树Kruskal)

某地区经过对城镇交通状况的调查,得到现有城镇间快速道路的统计数据,并提出“畅通工程”的目标:使整个地区任何两个城镇间都可以实现快速交通(但不一定有直接的快速道路相连,只要互相间接通过快速路可达即可)。现得到城镇道路统计表,表中列出了任意两城镇间修建快速路的费用,以及该道路是否已经修通的状态。现请你编写程序,计算出全地区畅通需要的最低成本。

输入格式:

输入的第一行给出村庄数目N (1N100);随后的N(N1)/2行对应村庄间道路的成本及修建状态:每行给出4个正整数,分别是两个村庄的编号(从1编号到N),此两村庄间道路的成本,以及修建状态 — 1表示已建,0表示未建。

输出格式:

输出全省畅通需要的最低成本。

输入样例:

4
1 2 1 1
1 3 4 0
1 4 1 1
2 3 3 0
2 4 2 1
3 4 5 0

输出样例:

3

题意

给你N个村庄,N*(N-1)/2条边,修建状态1表示两村庄已经连接,求连通全村庄要多少花费

题解

典型的最小生成树问题,Prim和Kruksal算法都可以用,这题应该算是稠密图用Prim更快,但这里N比较小,这里用Kruksal写了,已经连通的用并查集连通一下即可,模板题

代码

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 
 4 const int N=105,M=N*N;
 5 int n,m=0;
 6 int F[N];
 7 struct edge
 8 {
 9     int u,v,w;
10 }edges[M];
11 int Find(int x)
12 {
13     return F[x]==x?x:F[x]=Find(F[x]);
14 }
15 bool cmp(edge a,edge b)
16 {
17     return a.w<b.w;
18 }
19 int Kruskal()
20 {
21     sort(edges,edges+m,cmp);
22     int ans=0,cnt=0;
23     for(int i=0;i<m;i++)
24     {
25         int fu=Find(edges[i].u);
26         int fv=Find(edges[i].v);
27         if(fu!=fv)
28         {
29             F[fu]=fv;
30             ans+=edges[i].w;
31             cnt++;
32         }
33         if(cnt==n-1)break;
34     }
35     return ans;
36 }
37 int main()
38 {
39     int u,v,w,d;
40     cin>>n;
41     for(int i=1;i<=n;i++)F[i]=i;
42     for(int i=0;i<n*(n-1)/2;i++)
43     {
44         cin>>u>>v>>w>>d;
45         edges[m].u=u;
46         edges[m].v=v;
47         edges[m++].w=w;
48         if(d)
49         {
50             int fu=Find(u);
51             int fv=Find(v);
52             if(fu!=fv)
53                 F[fu]=fv;
54         }
55     }
56     printf("%d\n",Kruskal());
57     return 0;
58 }

posted on 2018-03-12 18:10  大桃桃  阅读(529)  评论(0编辑  收藏  举报

导航