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 } 
  • 相关阅读:
    算法训练 P1103
    算法训练 表达式计算
    算法训练 表达式计算
    基础练习 时间转换
    基础练习 字符串对比
    Codeforces 527D Clique Problem
    Codeforces 527C Glass Carving
    Codeforces 527B Error Correct System
    Codeforces 527A Glass Carving
    Topcoder SRM 655 DIV1 250 CountryGroupHard
  • 原文地址:https://www.cnblogs.com/iiyiyi/p/6071866.html
Copyright © 2011-2022 走看看