倍增LCA专题

说到倍增LCA,我不得不想起的就是NOIP2013货车运输。这题的原题其实是UVA11354。当年向SKYDEC学习了一下写法,但是不求甚解,只知道做法却不太明白所以然。后来也碰到过好几次类似的。最近想做个总结,首先重写了一遍这题,用白书上的写法。

UVA11354 给一张无向图,给出若干询问,每次询问两点间的最小瓶颈路的最大边长。(最小瓶颈路,即,使两点间的路径上的最长边最短这样的路)

题解:由最小生成树的性质可以知道,瓶颈路一定是在最小生成树上的。先求出MST,然后转化成有根树。然后对于每两个点之间的路径的最大边,只需要通过倍增LCA求的时候,顺便维护maxcost表示最大边长即可。

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 const int maxn=1e5+10;
  4 const int inf=(1<<30)-1;
  5 struct edge{
  6     int x,y,v;
  7     bool operator <(const edge &b) const {
  8         return v<b.v;
  9     }
 10 }a[maxn<<1];
 11 int n,m;
 12 struct node {
 13     int to,v;
 14 };
 15 vector<node> G[maxn];
 16 int f[maxn],d[maxn];
 17 int cost[maxn],fa[maxn];
 18 int anc[maxn][20],maxcost[maxn][20];
 19 int get(int x) {
 20     return (x==f[x])?x:f[x]=get(f[x]);
 21 }
 22 void dfs(int x,int pre,int dep) {
 23     d[x]=dep;
 24     int sz=G[x].size();
 25     for(int i=0;i<sz;i++) {
 26         node &e=G[x][i];
 27         int y=e.to,v=e.v;
 28         if(y==pre) continue;
 29         fa[y]=x;cost[y]=v;
 30         dfs(y,x,dep+1);
 31     }
 32 }
 33 void preprocess() {
 34     for(int i=1;i<=n;i++) {
 35         anc[i][0]=fa[i];maxcost[i][0]=cost[i];
 36         for(int j=1;(1<<j)<n;j++) anc[i][j]=-1;
 37     } 
 38     for(int j=1;(1<<j)<n;j++) {
 39         for(int i=1;i<=n;i++) {
 40             if(~anc[i][j-1]) {
 41                 int u=anc[i][j-1];
 42                 anc[i][j]=anc[u][j-1];
 43                 maxcost[i][j]=max(maxcost[i][j-1],maxcost[u][j-1]);
 44             }
 45         }
 46     }
 47 }
 48 int LCA(int p,int q) {
 49     int k;
 50     if(d[p]<d[q]) swap(p,q);
 51     for(k=1;(1<<k)<=d[p];k++);
 52     k--;
 53     int ans=-inf;
 54     for(int i=k;i>=0;i--)
 55     if(d[p]-(1<<i)>=d[q]) {
 56         ans=max(ans,maxcost[p][i]);
 57         p=anc[p][i];
 58     }
 59     if(p==q) return ans;
 60     for(int i=k;i>=0;i--) 
 61     if(~anc[p][i] && anc[p][i]!=anc[q][i]) {
 62         ans=max(ans,maxcost[p][i]);p=anc[p][i];
 63         ans=max(ans,maxcost[q][i]);q=anc[q][i];
 64     }
 65     ans=max(ans,cost[p]);
 66     ans=max(ans,cost[q]);
 67     return ans;//LCA = fa[p]
 68 }
 69 
 70 
 71 int main() {
 72     bool fir=1;
 73     while(~scanf("%d%d",&n,&m)) {
 74         if(fir) fir=0;
 75         else printf("\n");
 76         for(int i=1;i<=m;i++) {
 77             int x,y,v;scanf("%d%d%d",&x,&y,&v);
 78             a[i]=(edge){x,y,v};
 79         }
 80         sort(a+1,a+m+1);
 81         for(int i=0;i<=n;i++) G[i].clear(),f[i]=i;
 82         int cnt=0;
 83         for(int i=1;i<=m;i++) {
 84             int u=get(a[i].x),v=get(a[i].y);
 85             if(u!=v) {
 86                 f[u]=v;
 87                 G[u].push_back((node){v,a[i].v});
 88                 G[v].push_back((node){u,a[i].v});
 89                 if(++cnt==n-1) break;
 90             }
 91         }
 92         dfs(1,-1,0);
 93         preprocess();
 94         int Q;scanf("%d",&Q);
 95         while(Q--) {
 96             int x,y;scanf("%d%d",&x,&y);
 97             printf("%d\n",LCA(x,y));
 98         }
 99     }
100     return 0;
101 }
View Code

 

HDU2586 感觉RXDoi的写法超级优秀啊……学习了一下

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int inf=(1<<30)-1;
 4 const int maxn=100010;
 5 int IN(){
 6     int c,f,x;
 7     while (!isdigit(c=getchar())&&c!='-');c=='-'?(f=1,x=0):(f=0,x=c-'0');
 8     while (isdigit(c=getchar())) x=(x<<1)+(x<<3)+c-'0';return !f?x:-x;
 9 }
10 int n,m,x,y,z,T;
11 int head[maxn],tot;
12 struct data{
13     int to,next,v;
14 }e[maxn<<1];
15 int dep[maxn],dis[maxn];
16 int pa[maxn][20];
17 void init() {
18     memset(head,-1,sizeof(head));tot=0;
19 }
20 void Add(int x,int y,int v) {
21     e[tot]=(data){y,head[x],v};head[x]=tot++;
22     e[tot]=(data){x,head[y],v};head[y]=tot++;
23 }
24 void dfs(int x) {
25     for(int i=head[x],y;~i;i=e[i].next) {
26         if((y=e[i].to)==pa[x][0]) continue;
27         dep[y]=dep[x]+1;pa[y][0]=x;
28         dis[y]=dis[x]+e[i].v;dfs(y);
29     }
30 }
31 int LCA(int x,int y) {
32     if(dep[x]>dep[y]) swap(x,y);
33     for(int w=dep[y]-dep[x],i=0;w;w>>=1,i++) if(w&1) y=pa[y][i];
34     if(x==y) return x;
35     for(int i=19;~i;i--) if(pa[x][i]!=pa[y][i]) x=pa[x][i],y=pa[y][i];
36     return pa[x][0];
37 }
38 void Main() {
39     n=IN();m=IN();
40     init();
41     for(int i=1;i<n;i++) {
42         x=IN(),y=IN(),z=IN();
43         Add(x,y,z);
44     }
45     dep[1]=0;dfs(1);
46     for(int i=1;i<=n;i++) for(int j=1;j<20;j++) pa[i][j]=pa[pa[i][j-1]][j-1];
47     while(m--) x=IN(),y=IN(),printf("%d\n",dis[x]+dis[y]-2*dis[LCA(x,y)]);
48 }
49 int main()
50 {
51     for(int T=IN();T--;) Main();
52     return 0;
53 }
View Code

 

posted @ 2018-06-08 15:03  caozy623  阅读(213)  评论(0编辑  收藏  举报