• UVa 11354 邦德(最小瓶颈路+LCA)


    https://vjudge.net/problem/UVA-11354

    题意:

    有n个城市m条道路,每条道路有一个危险系数。先在有若干个询问,要求找到一条从s到t的路,使得途径所有边的最大危险系数最小。

    思路:

    最小瓶颈路肯定是在最小生成树上的。所有先求最小生成树。

    然后将它转化成有根树,让fa[i]和cost[i]分别表示结点i的父亲编号和它与父亲之间的边权L[i]表示结点i的深度。

    anc[i][j]表示结点i的第2^j级祖先的编号(j==0时候就是fa[i],如果第2^j祖先不存在,设为-1)。

    maxcost[i][j]表示结点i和第2^j级祖先之间路径上的最大权值。

      1 #include<iostream>
      2 #include<algorithm>
      3 #include<cstdio>
      4 #include<cstring>
      5 #include<string>
      6 #include<vector>
      7 #include<queue>
      8 #include<cmath>
      9 #include<map>
     10 using namespace std;
     11 typedef long long LL;
     12 const int maxn=50000+5;
     13 const int INF=0x3f3f3f;
     14 
     15 struct node
     16 {
     17     int u,v,d;
     18     bool operator < (const node& rhs) const
     19     {
     20         return d<rhs.d;
     21     }
     22 }edge[2*maxn];
     23 
     24 int n,m;
     25 int cnt;
     26 int p[maxn];
     27 vector<int> g[maxn];
     28 vector<int> c[maxn];
     29 
     30 int find(int x)
     31 {
     32     return x==p[x]?x:p[x]=find(p[x]);
     33 }
     34 
     35 struct LCA
     36 {
     37     int n;
     38     int fa[maxn];
     39     int cost[maxn];
     40     int L[maxn];
     41     int anc[maxn][25];  //结点i的第(1<<j)级祖先编号,anc[i][0]就是父亲fa[i],anc[i][j]=-1表示该祖先不存在
     42     int maxcost[maxn][25];  //结点i和它的(1<<j)级祖先之间的路径上的最大权值
     43 
     44     void preprocess()   //预处理
     45     {
     46         for(int i=0;i<n;i++)
     47         {
     48             anc[i][0]=fa[i]; maxcost[i][0]=cost[i];
     49             for(int j=1;(1<<j)<n;j++)  anc[i][j]=-1;
     50         }
     51         for(int j=1;(1<<j)<n;j++)
     52         {
     53             for(int i=0;i<n;i++)
     54                 if(anc[i][j-1]!=-1)
     55             {
     56                 int a=anc[i][j-1];
     57                 anc[i][j]=anc[a][j-1];
     58                 maxcost[i][j]=max(maxcost[i][j-1],maxcost[a][j-1]);
     59             }
     60         }
     61     }
     62 
     63     int query(int p,int q)
     64     {
     65         int tmp, log, i;
     66         if(L[p] < L[q]) swap(p,q);
     67         for(log=1; (1<<log) <= L[p]; log++);  log--;
     68 
     69         int ans=-INF;
     70         for(int i=log; i>=0;i--)
     71             if(L[p]-(1<<i)>=L[q])    //让p和q处于同一层
     72         {
     73             ans=max(ans,maxcost[p][i]);
     74             p=anc[p][i];
     75         }
     76 
     77         if(p==q)   return ans;  //LCA为p
     78 
     79         for(int i=log;i>=0;i--)
     80             if(anc[p][i]!=-1&&anc[p][i]!=anc[q][i])//否则,让p,q同时往上爬,保证爬的时候始终处于同一层
     81             {
     82                 ans=max(ans,maxcost[p][i]);p=anc[p][i];
     83                 ans=max(ans,maxcost[q][i]);q=anc[q][i];
     84             }
     85         ans=max(ans,cost[p]);
     86         ans=max(ans,cost[q]);
     87         return ans;  //LCA为fa[p](或fa[q])
     88     }
     89 }solver;
     90 
     91 void MST()
     92 {
     93     sort(edge,edge+cnt);
     94     int num=0;
     95     for(int i=0;i<cnt;i++)
     96     {
     97         int x=edge[i].u,y=edge[i].v;
     98         int u=find(x),v=find(y);
     99         if(u!=v)
    100         {
    101             p[u]=v;
    102             g[x].push_back(y); c[x].push_back(edge[i].d);
    103             g[y].push_back(x); c[y].push_back(edge[i].d);
    104             if(++cnt==n-1)  break;
    105         }
    106     }
    107 }
    108 
    109 void dfs(int u,int fa,int level)   //无根树转有根树
    110 {
    111     solver.L[u]=level;
    112     for(int i=0;i<g[u].size();i++)
    113     {
    114         int v=g[u][i];
    115         if(v!=fa)
    116         {
    117             solver.fa[v]=u;
    118             solver.cost[v]=c[u][i];  //cost就是v点到其父亲结点的权值
    119             dfs(v,u,level+1);
    120         }
    121     }
    122 }
    123 
    124 int main()
    125 {
    126     //freopen("D:\input.txt","r",stdin);
    127     int kase=1;
    128     while(~scanf("%d%d",&n,&m) && n)
    129     {
    130         cnt=0;
    131         for(int i=0;i<n;i++)  {p[i]=i;g[i].clear();c[i].clear();}
    132         for(int i=0;i<m;i++)
    133         {
    134             int x,y,d;
    135             scanf("%d%d%d",&x,&y,&d);
    136             edge[cnt].u=x-1;
    137             edge[cnt].v=y-1;
    138             edge[cnt].d=d;
    139             cnt++;
    140         }
    141         MST();
    142         dfs(0,-1,0);
    143         solver.n=n;
    144         solver.preprocess();
    145         int q;
    146         if(kase++!=1)  puts("");
    147         scanf("%d",&q);
    148         while(q--)
    149         {
    150             int x,y;
    151             scanf("%d%d",&x,&y);
    152             printf("%d
    ",solver.query(x-1,y-1));
    153         }
    154     }
    155     return 0;
    156 }
  • 相关阅读:
    有关mysql数据库的编码
    成功启动了Apache却没有启动apache服务器
    遍历元素绑定事件时作用域是怎么回事啊,为什么要用this关键字,而直接使用元素本身就不行?
    js中给函数传参函数时,函数加括号与不加括号的区别
    win64安装及配置apache+php+mysql
    ubuntu 12.04 安装nginx
    ubuntu下怎么显示右上角的小键盘
    ubuntu12.04安装Vmware Tools
    PyCharm教程
    jira使用指南
  • 原文地址:https://www.cnblogs.com/zyb993963526/p/6874289.html
Copyright © 2020-2023  润新知