zoukankan      html  css  js  c++  java
  • 最小瓶颈生成树

    所谓最小瓶颈生成树....就是使得生成树树上最大边权值最小。

    这里主要介绍一种期望O(M)(线性)的求法,其实主要就是二分,具体思路如下:

    类比找第k大值的方法,首先随机一个边权w。

    然后将不超过这个边权的边加入,遍历这张图。

    如果图连通,那么瓶颈不超过w,于是只需考虑边权不超过w的边。

    否则将这些连通点缩起来,考虑边权大于w的边。

    每次将问题的规模缩小至一半。

    期望时间复杂度O(m)。

    相关例题有两道:

    A.Hangar Hurdles (CERC 16)

    有一个n*n的网格图,上面有些格子可行,有些格子是障碍。 有Q个询问,想把一个正方形箱子从(r1,c1)推到(r2,c2),问箱子最大的大小。(起点终点是正方形箱子的中点) N<=1000 Q<=300000

    B.洪蛤吨有一个宽度为L的管道,我们可以视其为一条y=L的直线与X轴所夹的部分。

    (所以这根管道的长度可以视为正无穷)

    这个管道中有个N个障碍点,第i个障碍点的坐标为(Xi,Yi)

    已知有一个球体,能在不碰到障碍点的前提下,从管道的最左端走到最右端。(即从管道内横坐标负无穷的地方走到横坐标正无穷的地方)。

    求这个球体的直径最大是多少。为了避免精度误差,请输出答案保留三位小数的结果。

    两题有异曲同工之妙a...(/滑稽,思路差不多...)都可以用最小瓶颈树实现复杂度最小

    下面上一下t2的代码:(没有用最小瓶颈树优化,逃)

     1 #include<bits/stdc++.h>
     2 #define maxn 505
     3 using namespace std;
     4 struct eage{
     5     int u,v;
     6     double dist;
     7 }e[maxn*maxn/2+maxn*2];
     8 bool cmp(eage a,eage b){
     9     return a.dist<b.dist;
    10 }
    11 double dis(int x1,int y1,int x2,int y2){
    12     return sqrt(1.0*(x1-x2)*(x1-x2)+1.0*(y1-y2)*(y1-y2)); 
    13 }
    14 int fa[maxn];
    15 int find(int x){
    16     if(fa[x]==x) return x;
    17     int root=find(fa[x]);
    18     fa[x]=root;
    19     return root;
    20 }
    21 void link(int x,int y){
    22     int fx=find(x),fy=find(y);
    23     if(fx!=fy){
    24         fa[fx]=fy;
    25     } 
    26 }
    27 bool check(int x,int y){
    28     int fx=find(x),fy=find(y);
    29     if(fx!=fy) return false;
    30     return true;
    31 }
    32 int l,n;
    33 struct node{
    34     int x,y;
    35 }nd[maxn];
    36 void init(){
    37     int pos=0;
    38     scanf("%d%d",&n,&l);
    39     for(int i=1;i<=n+2;i++) fa[i]=i;//n+1是上,n+2是下 
    40     for(int i=1;i<=n;i++){
    41         scanf("%d%d",&nd[i].x,&nd[i].y);
    42     }
    43     for(int i=1;i<=n;i++){
    44         e[++pos]=(eage){i,n+1,l-nd[i].y};
    45         e[++pos]=(eage){i,n+2,nd[i].y};
    46     for(int j=i+1;j<=n;j++){
    47         e[++pos]=(eage){i,j,dis(nd[i].x,nd[i].y,nd[j].x,nd[j].y)};
    48     }
    49     }
    50     int cnt=0;
    51     sort(e+1,e+pos+1,cmp);
    52     for(int i=1;i<=pos;i++){
    53         int u=e[i].u,v=e[i].v;
    54         if(check(u,v)) continue;
    55         link(u,v);
    56         cnt++;
    57         if(find(n+1)==find(n+2)){//只要上底和下底连接了就行 这样才能保证极大值可以通过
    58                                  //如果后面更大,那这里是过不了的 
    59             printf("%.3f",e[i].dist);
    60             break;
    61         }
    62     }
    63 }
    64 int main(){
    65     init();
    66     
    67     return 0;
    68 }
  • 相关阅读:
    VS与ultraedit 正则表达式替换
    Java学习第十七天
    Java学习第十六天
    Java学习第十五天
    Java学习第十四天
    Java学习第十三天
    Java学习第十二天
    Java学习第十一天
    Java学习第十天
    Java学习第九天
  • 原文地址:https://www.cnblogs.com/degage/p/9740739.html
Copyright © 2011-2022 走看看