zoukankan      html  css  js  c++  java
  • BZOJ_1626_[Usaco2007_Dec]_Building_Roads_修建道路_(Kruskal)

    描述


    http://www.lydsy.com/JudgeOnline/problem.php?id=1626

    给出(n)个点的坐标,其中一些点已经连通,现在要把所有点连通,求修路的最小长度.

    分析


    已经连好一些边的最小生成树问题.

    这里顺带复习了一下Prim和Krusakal.

    Prim的证明:

    设当前已经连好的树为(T),当前最小的边为(e),我们来证明(e)一定在最小生成树(G)中.

    假设(e)不在(G)中,则连通(G-T)和(T)的边(e')一定比(e)大(或相等).此时我们在(G)中加入(e),会形成环,去掉环中的(e'),树依然连通,而花费更小了,这与(G)是最小生成树矛盾.(如果(e)与(e')相等那么虽然花费不会更小,也就是说(e)可以不再(G)中,但是我们也可以用(e)替换(e'),换言之,(e)在(G)中是不错误的.)

    所以(e)一定在最小生成树(G)中.

    Kruskal的证明:

    设当前连接两个不连通分量的最小的边为(e),我们来证明(e)一定在最小生成树(G)中.

    假设(e)不再(G)中,则连通这两个分量的边(e')一定比(e)大(或相等).此时我们 在(G)中加入(e),会形成环,去掉环中的(e'),树依然连通,而花费更小了,这与(G)是最小生成树矛盾.(如果(e)与 (e')相等那么虽然花费不会更小,也就是说(e)可以不再(G)中,但是我们也可以用(e)替换(e'),换言之,(e)在 (G)中是不错误的.)

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 
     4 const int maxn=1000+5;
     5 struct pt{
     6     double x,y;
     7     pt(double x=0,double y=0):x(x),y(y){}
     8 }p[maxn];
     9 struct edge{
    10     int from,to;
    11     double d;
    12     edge(){}
    13     edge(int from,int to,double d):from(from),to(to),d(d){}
    14     bool operator < (const edge &rhs) const { return d<rhs.d; }
    15 }g[maxn*maxn];
    16 int n,m,cnt=1;
    17 int f[maxn];
    18 double ans;
    19 inline double dis(pt a,pt b){ return sqrt(pow(a.x-b.x,2)+pow(a.y-b.y,2)); }
    20 inline int find(int x){ return x==f[x]?x:f[x]=find(f[x]); }
    21 int main(){
    22     scanf("%d%d",&n,&m);
    23     for(int i=1;i<=n;i++){
    24         scanf("%lf%lf",&p[i].x,&p[i].y);
    25         f[i]=i;
    26     }
    27     for(int i=1;i<=m;i++){
    28         int u,v; scanf("%d%d",&u,&v);
    29         int fu=find(u),fv=find(v);
    30         if(fu!=fv) f[fu]=fv,cnt++;
    31     }
    32     for(int i=1;i<=n;i++)for(int j=1;j<=n;j++) g[(i-1)*n+j]=edge(i,j,dis(p[i],p[j]));
    33     sort(g+1,g+1+n*n);
    34     int tot=n*n;
    35     for(int i=1;i<=tot,cnt<=n;i++){
    36         int fx=find(g[i].from),fy=find(g[i].to);
    37         if(fx!=fy){
    38             f[fx]=fy;
    39             ans+=dis(p[g[i].from],p[g[i].to]);
    40             cnt++;
    41         }
    42     }
    43     printf("%.2lf
    ",ans);
    44     return 0;
    45 }
    View Code
  • 相关阅读:
    【外企面试】求一个链表中环的入口【强势证明】
    LeetCode5. Longest Palindromic Substring 最长回文子串 4种方法
    LeetCode4. Median of Two Sorted Arrays---vector实现O(log(m+n)--- findkth
    PAT1030 Travel Plan (30)---DFS
    LeetCode3. Longest Substring Without Repeating Characters
    LeetCode 题目总结/分类
    PAT1029.Median (25)
    PAT1028. List Sorting (25)---strcmp
    重新开始征程
    Dotnet文件格式解析
  • 原文地址:https://www.cnblogs.com/Sunnie69/p/5581419.html
Copyright © 2011-2022 走看看