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 }
  • 相关阅读:
    pat甲级 1155 Heap Paths (30 分)
    pat甲级 1152 Google Recruitment (20 分)
    蓝桥杯 基础练习 特殊回文数
    蓝桥杯 基础练习 十进制转十六进制
    蓝桥杯 基础练习 十六进制转十进制
    蓝桥杯 基础练习 十六进制转八进制
    51nod 1347 旋转字符串
    蓝桥杯 入门训练 圆的面积
    蓝桥杯 入门训练 Fibonacci数列
    链表相关
  • 原文地址:https://www.cnblogs.com/degage/p/9740739.html
Copyright © 2011-2022 走看看