zoukankan      html  css  js  c++  java
  • uva 11354(最小瓶颈路--多组询问 MST+LCA倍增)

    题意:给你一张无向图,然后有若干组询问,让你输出a->b的最小瓶颈路。

    思路:又是一道最小瓶颈路的题目。以前做过单组询问的,由郭华阳在集训队论文里提到的性质。在单组询问的时候只需要求出kurskal算大过程中第一次将他们合并的边就好了。但是对于这道题的多组询问,我们就不能那么处理了。在郭华阳的论文里讲到了一种方法每次合并时生成一个节点,把待合并的两个集合看成两颗子树,这样最终我们就只要对于询问的两个节点,求出他LCA的权值即可。

    如图所示。但是这里我所采用的是另一种方法。就是dis[i][j]数组维护的是j号结点到2^i祖先的瓶颈路。这样我们把lca的查询过程稍稍修改一下就可以了。

    代码如下:

      1 #include <iostream>
      2 #include <cstdio>
      3 #include <cstdlib>
      4 #include <cmath>
      5 #include <cstring>
      6 #include <algorithm>
      7 #include <queue>
      8 #include <stack>
      9 #include <vector>
     10 #include <set>
     11 #include <map>
     12 #define MP(a, b) make_pair(a, b)
     13 #define PB(a) push_back(a)
     14 
     15 using namespace std;
     16 
     17 typedef long long ll;
     18 typedef pair<int ,int> pii;
     19 typedef pair<unsigned int, unsigned int> puu;
     20 typedef pair<int ,double> pid;
     21 typedef pair<ll, int> pli;
     22 typedef pair<int, ll> pil;
     23 
     24 const int INF = 0x3f3f3f3f;
     25 const double eps = 1e-6;
     26 const int LEN = 100000+10;
     27 const int LOG_LEN = 25;
     28 struct edge{int from, to;ll val;};
     29 vector<pil> Map[LEN];
     30 edge e[LEN];
     31 int n, m, fa[LEN], q, qa, qb, parent[LOG_LEN][LEN], depth[LEN];
     32 ll dis[LOG_LEN][LEN];
     33 bool cmp(edge a, edge b){return a.val<b.val;}
     34 //UFSET
     35 void init(){for(int i=0; i<LEN; i++)fa[i] = i;}
     36 int Find(int a){return fa[a]==a?a:Find(fa[a]);}
     37 void Union(int a, int b){int pa = Find(a), pb = Find(b);if(pa!=pb)fa[pa] = pb;}
     38 
     39 //Use Kruskal to build MST
     40 void Kruskal()
     41 {
     42     sort(e, e+m, cmp);
     43     init();
     44     int cnt = 0;
     45     for(int i=0; i<m; i++){
     46         int a = e[i].from, b = e[i].to;
     47         ll v = e[i].val;
     48         if(Find(a) == Find(b))continue;
     49         Union(a, b);
     50         Map[a].PB(MP(b,v));
     51         Map[b].PB(MP(a,v));
     52         cnt++;
     53         if(cnt == n-1) return ;
     54     }
     55 }
     56 
     57 //LCA
     58 void dfs(int v, int f, int d)
     59 {
     60     parent[0][v] = f;
     61     dis[0][v] = -1;
     62     depth[v] = d;
     63     for(int i=0; i<Map[v].size(); i++){
     64         pil nv = Map[v][i];
     65         if(nv.first!=f) dfs(nv.first, v, d+1);
     66         else dis[0][v] = nv.second;
     67     }
     68 }
     69 
     70 void init_lca()
     71 {
     72     memset(dis, 0, sizeof dis);
     73     memset(depth, -1, sizeof depth);
     74     for(int i=1; i<=n; i++)if(depth[i]<0)dfs(i, -1, 0);
     75     for(int k=0; k+1<LOG_LEN; k++){
     76         for(int i=1; i<=n; i++){
     77             if(parent[k][i]<0) parent[k+1][i] = dis[k+1][i] = -1;
     78             else {
     79                 parent[k+1][i] = parent[k][parent[k][i]];
     80                 dis[k+1][i] = max(dis[k][i], dis[k][parent[k][i]]);
     81             }
     82         }
     83     }
     84 }
     85 
     86 ll lca(int u, int v)
     87 {
     88     if(depth[v] > depth[u]) swap(u, v);
     89     ll ret = 0;
     90     for(int i=0; i<LOG_LEN; i++){
     91         if((depth[u]-depth[v]) >> i & 1) {
     92             ret = max(ret, dis[i][u]);
     93             u = parent[i][u];
     94         }
     95     }
     96     if(u==v) return ret;
     97     for(int i=LOG_LEN-1; i>=0; i--){
     98         if(parent[i][u]!=parent[i][v]){
     99             ret = max(ret, dis[i][u]);
    100             ret = max(ret, dis[i][v]);
    101             u = parent[i][u];v = parent[i][v];
    102         }
    103     }
    104     ret = max(ret, dis[0][u]);
    105     ret = max(ret, dis[0][v]);
    106     return ret;
    107 }
    108 
    109 int main()
    110 {
    111 //    freopen("in.txt", "r", stdin);
    112 
    113     int kase = 1;
    114     while(scanf("%d%d", &n, &m)!=EOF)
    115     {
    116         kase == 1? kase++:puts("");
    117         for(int i=0; i<LEN; i++)Map[i].clear();
    118         for(int i=0; i<m; i++)scanf("%d%d%lld", &e[i].from, &e[i].to, &e[i].val);
    119         Kruskal();
    120         init_lca();
    121         scanf("%d", &q);
    122         for(int i=0; i<q; i++){
    123             scanf("%d%d", &qa, &qb);
    124             printf("%lld
    ", lca(qa, qb));
    125         }
    126     }
    127     return 0;
    128 }
    View Code
    奔跑吧!少年!趁着你还年轻
  • 相关阅读:
    centos“You don't have permission to access /index.html on this server.”
    使用yum来安装或卸载CentOS图形界面包
    PHP上IIS上显示服务器应用程序不可用
    Windows 2003 远程桌面连接数超过最大连接数终极解决方案
    perl清理电脑上重复的文件
    wordpress在IIS6上首页访问不了
    WordPress首页出现循环重定向解决办法四则(转载)
    windows server 2003 如何在远程链接时更改用户密码
    Ubuntu下安装php5gd库,支持jpg、png、gif等格式图片处理
    wordpress设置用163邮箱账号发送邮件
  • 原文地址:https://www.cnblogs.com/shu-xiaohao/p/3532800.html
Copyright © 2011-2022 走看看