zoukankan      html  css  js  c++  java
  • [BZOJ3732]Network

    题目大意:
      一个$n(nle15000)$个点,$m(mle30000)$条边的无向图,每条边有一个边权$w_i$,$q(qle20000)$次询问,每次询问点$(u,v)$所有路径中权值最大的边最小值是多少。

    思路:
      LCA模板题,这里考虑使用Kruskal重构树。对于排完序的边新建一个虚点,权值为边权,作为两个顶点子树的父结点。询问时相当于询问重构树上两点LCA点权。

     1 #include<cstdio>
     2 #include<cctype>
     3 #include<cstring>
     4 #include<algorithm>
     5 inline int getint() {
     6     register char ch;
     7     while(!isdigit(ch=getchar()));
     8     register int x=ch^'0';
     9     while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
    10     return x;
    11 }
    12 const int N=3e4,logN=15,M=6e4,M2=3e4;
    13 struct Edge {
    14     int to,next;
    15 };
    16 Edge e[M];
    17 int h[N],sz,tot,n,m,q,val[N],dep[N],anc[N][logN];
    18 inline void add_edge(const int &u,const int &v) {
    19     e[sz]=(Edge){v,h[u]};h[u]=sz++;
    20 }
    21 struct Edge2 {
    22     int u,v,w;
    23     bool operator < (const Edge2 &another) const {
    24         return w<another.w;
    25     }
    26 };
    27 Edge2 e2[M2];
    28 struct DisjointSet {
    29     int anc[N];
    30     DisjointSet() {
    31         for(register int i=0;i<N;i++) anc[i]=i;
    32     }
    33     int find(const int &x) {
    34         return x==anc[x]?x:anc[x]=find(anc[x]);
    35     }
    36     void merge(const int &x,const int &y) {
    37         anc[find(x)]=find(y);
    38     }
    39     bool same(const int &x,const int &y) {
    40         return find(x)==find(y);
    41     }
    42 };
    43 DisjointSet s;
    44 inline void kruskal() {
    45     std::sort(&e2[0],&e2[m]);
    46     for(register int i=0;i<m;i++) {
    47         const int u=e2[i].u,v=e2[i].v,w=e2[i].w;
    48         if(!s.same(u,v)) {
    49             val[++tot]=w;
    50             add_edge(tot,s.find(u));
    51             add_edge(tot,s.find(v));
    52             s.merge(u,tot);
    53             s.merge(v,tot);
    54         }
    55     }
    56 }
    57 inline int log2(const float &x) {
    58     return ((unsigned&)x>>23&255)-127;
    59 }
    60 void dfs(const int &x,const int &par) {
    61     dep[x]=dep[anc[x][0]=par]+1;
    62     for(register int i=1;i<=log2(dep[x]);i++) {
    63         anc[x][i]=anc[anc[x][i-1]][i-1];
    64     }
    65     for(register int i=h[x];~i;i=e[i].next) {
    66         const int &y=e[i].to;
    67         dfs(y,x);
    68     }
    69 }
    70 inline int lca(int x,int y) {
    71     if(dep[x]!=dep[y]) {
    72         if(dep[x]<dep[y]) std::swap(x,y);
    73         for(register int i=log2(dep[x]-dep[y]);~i;i--) {
    74             if(dep[anc[x][i]]>=dep[y]) x=anc[x][i];
    75         }
    76     }
    77     if(x==y) return x;
    78     for(register int i=log2(dep[x]);~i;i--) {
    79         if(anc[x][i]!=anc[y][i]) {
    80             x=anc[x][i];
    81             y=anc[y][i];
    82         }
    83     }
    84     return anc[x][0];
    85 }
    86 int main() {
    87     memset(h,-1,sizeof h);
    88     n=tot=getint(),m=getint(),q=getint();
    89     for(register int i=0;i<m;i++) {
    90         const int u=getint(),v=getint(),w=getint();
    91         e2[i]=(Edge2){u,v,w};
    92     }
    93     kruskal();
    94     dfs(tot,0);
    95     for(register int i=0;i<q;i++) {
    96         printf("%d
    ",val[lca(getint(),getint())]);
    97     }
    98     return 0;
    99 }
  • 相关阅读:
    Ubuntu 14.04 LTS 系统空间不足,输入密码后,无法进入桌面的解决办法
    语言代码表
    在WPS中删除整行的快捷键是什么?
    Google浏览器&插件
    Linux命令大全
    Python下载安装
    Tiobe最新编程语言排行
    windows 清理利器
    如何用VBA实现格式刷的功能?
    武侠音乐精装
  • 原文地址:https://www.cnblogs.com/skylee03/p/8696663.html
Copyright © 2011-2022 走看看