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

Leohh發表於2017-09-29

題目連結: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 }

 

相關文章