某地区经过对城镇交通状况的调查,得到现有城镇间快速道路的统计数据,并提出“畅通工程”的目标:使整个地区任何两个城镇间都可以实现快速交通(但不一定有直接的快速道路相连,只要互相间接通过快速路可达即可)。现得到城镇道路统计表,表中列出了任意两城镇间修建快速路的费用,以及该道路是否已经修通的状态。现请你编写程序,计算出全地区畅通需要的最低成本。
输入格式:
输入的第一行给出村庄数目N (1≤N≤100);随后的N(N−1)/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 }