zoukankan      html  css  js  c++  java
  • BZOJ 1626 [Usaco2007 Dec]Building Roads 修建道路:kruskal(最小生成树)

    题目链接: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 }
  • 相关阅读:
    作业要求 20201022-1 每周例行报告
    作业要求 20201015-3 每周例行报告
    20201008-1 每周例行报告
    20200924-1 每周例行报告
    总结
    20201126-1 每周例行报告
    20201120-1 每周例行报告
    20201112-1 每周例行报告
    20201105-1 每周例行报告
    20201029-1 每周例行报告
  • 原文地址:https://www.cnblogs.com/Leohh/p/7609189.html
Copyright © 2011-2022 走看看