题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1626
题意:
有n个农场,坐标为(x[i],y[i])。
有m条原先就修好的路,连接农场(a[i],b[i])。
现在要修一些路(首尾连接两个农场,长度为欧几里得距离),使得所有农场互相连通。
问修路的最短总距离。
题解:
最小生成树。
提前将m对点合并,再求最小生成树。
注:最后所有选出的边(包括原先的边)构成的并不一定是一棵树,因为原先的路中可能有环。
所以kruskal中不用判断cnt == n-1。
AC Code:
1 #include <iostream> 2 #include <stdio.h> 3 #include <string.h> 4 #include <math.h> 5 #include <algorithm> 6 #include <vector> 7 #define MAX_N 1005 8 9 using namespace std; 10 11 struct Edge 12 { 13 int sour; 14 int dest; 15 double len; 16 Edge(int _sour,int _dest,double _len) 17 { 18 sour=_sour; 19 dest=_dest; 20 len=_len; 21 } 22 Edge(){} 23 friend bool operator < (const Edge &a,const Edge &b) 24 { 25 return a.len<b.len; 26 } 27 }; 28 29 int n,m; 30 int x[MAX_N]; 31 int y[MAX_N]; 32 int par[MAX_N]; 33 double ans; 34 vector<Edge> edge; 35 36 void init_union_find() 37 { 38 for(int i=1;i<=n;i++) 39 { 40 par[i]=i; 41 } 42 } 43 44 int find(int x) 45 { 46 return par[x]==x?x:par[x]=find(par[x]); 47 } 48 49 void unite(int x,int y) 50 { 51 int px=find(x); 52 int py=find(y); 53 if(px==py) return; 54 par[px]=py; 55 } 56 57 bool same(int x,int y) 58 { 59 return find(x)==find(y); 60 } 61 62 void read() 63 { 64 // cin>>n>>m; 65 scanf("%d%d",&n,&m); 66 init_union_find(); 67 for(int i=1;i<=n;i++) 68 { 69 // cin>>x[i]>>y[i]; 70 scanf("%d%d",&x[i],&y[i]); 71 } 72 int a,b; 73 for(int i=0;i<m;i++) 74 { 75 // cin>>a>>b; 76 scanf("%d%d",&a,&b); 77 unite(a,b); 78 } 79 } 80 81 inline double cal_len(int a,int b) 82 { 83 long long v1=(long long)x[a]-x[b]; 84 long long v2=(long long)y[a]-y[b]; 85 return sqrt(v1*v1+v2*v2); 86 } 87 88 void build_graph() 89 { 90 for(int i=1;i<=n;i++) 91 { 92 for(int j=1;j<i;j++) 93 { 94 edge.push_back(Edge(i,j,cal_len(i,j))); 95 } 96 } 97 } 98 99 double kruskal() 100 { 101 sort(edge.begin(),edge.end()); 102 double res=0; 103 for(int i=0;i<edge.size();i++) 104 { 105 Edge temp=edge[i]; 106 if(!same(temp.sour,temp.dest)) 107 { 108 res+=temp.len; 109 unite(temp.sour,temp.dest); 110 } 111 } 112 return res; 113 } 114 115 void solve() 116 { 117 build_graph(); 118 ans=kruskal(); 119 } 120 121 void print() 122 { 123 printf("%.2f ",ans); 124 } 125 126 int main() 127 { 128 read(); 129 solve(); 130 print(); 131 }