1. 程式人生 > >BZOJ 1626 [Usaco2007 Dec]Building Roads 修建道路:kruskal(最小生成樹)

BZOJ 1626 [Usaco2007 Dec]Building Roads 修建道路:kruskal(最小生成樹)

push_back spa pri family sca iostream 長度 con end

題目鏈接: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\n",ans); 124 } 125 126 int main() 127 { 128 read(); 129 solve(); 130 print(); 131 }

BZOJ 1626 [Usaco2007 Dec]Building Roads 修建道路:kruskal(最小生成樹)