zoukankan      html  css  js  c++  java
  • 【LCA+MST】BZOJ3732-Network

    【题目大意】

    给你N个点的无向图 (1 <= N <= 15,000),记为:1…N。图中有M条边 (1<=M<=30,000) ,第j条边的长度:d_j (1<=d_j <=1,000,000,000)。现在有 K个询问 (1 < = K < = 15,000), 每个询问的格式是:A B,表示询问从A点走到B点的所有路径中,最长的边最小值是多少?

    【思路】

    显然,最小的最长边应该在MST上。先跑出MST,然后对于每个询问跑LCA,在跑LCA的过程中顺便处理最长边。

    LCA处理最长边是第一次写,但是这种东西,yy一下就好了,和LCA里面的祖先数组长得是一样的啊……

    【错误点】

    LCA是最后a的父亲,所以我们还要比较一下a和它父亲的连边……

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 const int MAXN=15000+50;
      4 const int MAXM=30000+50;
      5 const int DEG=20;
      6 struct Edge
      7 {
      8     int u,v,w;
      9     bool operator < (const Edge &x) const
     10     {
     11         return w<x.w;
     12     };
     13 };
     14 Edge edge[MAXM];
     15 vector<Edge> E[MAXN];
     16 int n,m,k;
     17 int u[MAXN],h[MAXN];
     18 int dep[MAXN],anc[MAXN][DEG],maxlen[MAXN][DEG];
     19 
     20 void addedge(int u,int v,int w)
     21 {
     22     E[u].push_back((Edge){u,v,w});
     23     E[v].push_back((Edge){v,u,w});
     24 }
     25 
     26 int find(int x)
     27 {
     28     int r=x;
     29     while (u[r]!=r) r=u[r];
     30     int tmp;
     31     while (u[x]!=x)
     32     {
     33         tmp=u[x];
     34         u[x]=r;
     35         x=tmp;
     36     }
     37     return r;
     38 }
     39 
     40 void union_set(int fa,int fb)
     41 {
     42     if (h[fa]>=h[fb])
     43     {
     44         u[fb]=fa;
     45         if (h[fa]==h[fb]) h[fa]++;
     46     }
     47     else u[fa]=fb;
     48 }
     49 
     50 void dfs(int u,int fa,int d)
     51 {
     52     anc[u][0]=fa;
     53     dep[u]=d;
     54     for (int i=0;i<E[u].size();i++)
     55     {
     56         int to=E[u][i].v;
     57         if (to==fa) continue;
     58         maxlen[to][0]=E[u][i].w;
     59         dfs(to,u,d+1);
     60     }
     61 }
     62 
     63 void getanc()
     64 {
     65     for (int i=1;i<DEG;i++)
     66         for (int j=1;j<=n;j++)
     67         {
     68             anc[j][i]=anc[anc[j][i-1]][i-1];
     69             maxlen[j][i]=max(maxlen[j][i-1],maxlen[anc[j][i-1]][i-1]);
     70         }
     71 }
     72 
     73 int swim(int x,int H,int &ret)
     74 {
     75     for (int i=0;H>0;i++)
     76     {
     77         if (H&1) ret=max(ret,maxlen[x][i]),x=anc[x][i];//swim过程中不要忘记更新ret 
     78         H/=2;
     79     }
     80     return x;
     81 }
     82 
     83 int lca(int a,int b)
     84 {
     85     int ret=-1;
     86     if (dep[a]<dep[b]) swap(a,b);
     87     a=swim(a,dep[a]-dep[b],ret);
     88     if (a==b) return ret;
     89     for (int i=DEG-1;i>=0;i--)
     90     {
     91         if (anc[a][i]!=anc[b][i])
     92         {
     93             ret=max(ret,maxlen[a][i]);
     94             a=anc[a][i];
     95             ret=max(ret,maxlen[b][i]);
     96             b=anc[b][i];
     97         }
     98     }
     99     ret=max(ret,maxlen[a][0]);//最后一条和父亲的连边不要忘记 
    100     ret=max(ret,maxlen[b][0]);
    101     return (ret);
    102 }
    103 
    104 
    105 void init()
    106 {
    107     scanf("%d%d%d",&n,&m,&k);
    108     for (int i=1;i<=m;i++)
    109         scanf("%d%d%d",&edge[i].u,&edge[i].v,&edge[i].w);
    110     for (int i=1;i<=n;i++) u[i]=i,h[i]=1;
    111 }
    112 
    113 void kruskal()
    114 {
    115     sort(edge+1,edge+m+1);
    116     for (int i=1;i<=m;i++)
    117     {
    118         int a=edge[i].u,b=edge[i].v;
    119         int fa=find(a),fb=find(b);
    120         if (fa!=fb)
    121         {
    122             union_set(fa,fb);
    123             addedge(edge[i].u,edge[i].v,edge[i].w);
    124         }
    125     }
    126 }
    127 
    128 void query()
    129 {
    130     dfs(1,0,1); 
    131     getanc();
    132     for (int i=0;i<k;i++)
    133     {
    134         int a,b;
    135         scanf("%d%d",&a,&b);
    136         printf("%d
    ",lca(a,b));
    137     }
    138 }
    139 
    140 int main()
    141 {
    142     init();
    143     kruskal();
    144     query();
    145     return 0;
    146 } 
  • 相关阅读:
    layui穿梭框右侧增加上移下移功能
    java.lang.NullPointerException出现的几种原因:
    springboot+thymeleaf+mybatis 基础学习
    Vue 生命周期扫盲
    Token 认证(Asp.Net)
    从具体化“system.decimal”类型到“system.string”类型的指定强制转换无效
    【C#】委托和Lambda表达式
    Visual Studio 2017添加visionPro控件
    从WinForm程序中看委托和事件
    西门子PLC通讯-仿真环境搭建
  • 原文地址:https://www.cnblogs.com/iiyiyi/p/6071866.html
Copyright © 2011-2022 走看看