【 lca倍增模板】

题目描述

对于 n(<100000)个点 n-1 条掉权值的边,有 m 个询问,每条询问求两个结点之间的路径上边权的最小值

输入

第一行 n,表示结点个数,接下来 n-1 行,每行 a b w 表示 a 与 b 之间有一条权值为 w的双向边
第 n+1 行:m 表示询问的个数,接下来 m 行,每行一个询问 a 和 b

输出

对于每个询问,输出两个结点的路径上边权的最小值

样例输入

10 1 4 11161 3 8 7244 5 9 635 1 10 23999 10 6 23998 7 5 16083 4 3 7145 1 7 20425 3 2 25701 14 1 5 9 3 3 1 7 5 9 1 5 1 1 7 3 1 1 8 1 3 7 6 5 7 7 1 1 7

样例输出

16083 635 7145 16083 635 16083 20425 7145 7145 7145 20425 16083 20425 20425
 
题解:
发个模版,坑爹数据,dfs栈溢出,于是改成bfs
  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  5 #include<cmath>
  6 using namespace std;
  7 const int N=100005,INF=1999999999;
  8 int head[N],num=1;
  9 struct Lin
 10 {
 11     int next,to,dis;
 12 }a[N<<1];
 13 void init(int x,int y,int z)
 14 {
 15     a[++num].next=head[x];
 16     a[num].to=y;
 17     a[num].dis=z;
 18     head[x]=num;
 19 }
 20 int gi(){
 21     int str=0,f=1;char ch=getchar();
 22     while(ch>'9' || ch<'0'){if(ch=='-')f=-1;ch=getchar();}
 23     while(ch>='0' && ch<='9')str=str*10+ch-'0',ch=getchar();
 24     return str*f;
 25 }
 26 int n,fa[N][21],dis[N][21],dep[N],q[N];
 27 void bfs()
 28 {
 29     dep[1]=1;
 30     int t=0,sum=1,x,u;
 31     q[1]=1;
 32     while(t!=sum)
 33     {
 34         x=q[++t];
 35         for(int i=head[x];i;i=a[i].next)
 36         {
 37             u=a[i].to;
 38             if(dep[u])continue;
 39             q[++sum]=u;dep[u]=dep[x]+1;
 40             dis[u][0]=a[i].dis;fa[u][0]=x;
 41         }
 42     }
 43 }
 44 int maxdep;
 45 void prework()
 46 {
 47     for(int j=1;j<=maxdep;j++)
 48         for(int i=1;i<=n;i++)
 49             fa[i][j]=fa[fa[i][j-1]][j-1];
 50     for(int j=1;j<=maxdep;j++)
 51         for(int i=1;i<=n;i++)
 52             dis[i][j]=min(dis[i][j-1],dis[fa[i][j-1]][j-1]);
 53 }
 54 void Clear()
 55 {
 56     for(int j=0;j<=maxdep;j++)
 57         for(int i=1;i<=n;i++)dis[i][j]=INF;
 58 }
 59 int lca(int x,int y)
 60 {
 61     if(dep[x]<dep[y])swap(x,y);
 62     int deep=dep[x]-dep[y];
 63     int ans=INF;
 64     for(int i=maxdep;i>=0;i--)
 65     {
 66         if(deep&(1<<i))
 67         {
 68             if(dis[x][i]<ans)ans=dis[x][i];
 69             x=fa[x][i];
 70         }
 71     }
 72     if(x==y)return ans;
 73     for(int i=maxdep;i>=0;i--)
 74     {
 75         if(fa[x][i]!=fa[y][i])
 76         {
 77             if(dis[x][i]<ans)ans=dis[x][i];
 78             if(dis[y][i]<ans)ans=dis[y][i];
 79             x=fa[x][i];y=fa[y][i];
 80         }
 81     }
 82     return min(ans,min(dis[x][0],dis[y][0]));
 83 }
 84 int main()
 85 {
 86     n=gi();
 87     maxdep=log(n)/log(2)+1;
 88     int x,y,z;
 89     Clear();
 90     int ca;
 91     for(int i=1;i<n;i++)
 92     {
 93         x=gi();y=gi();z=gi();
 94         init(x,y,z);init(y,x,z);
 95     }
 96     bfs();
 97     prework();
 98     int m=gi();
 99     while(m--)
100     {
101         x=gi();y=gi();
102         ca=lca(x,y);
103         printf("%d\n",lca(x,y));
104     }
105     return 0;
106 }

 

posted @ 2017-06-15 21:41  PIPIBoss  阅读(206)  评论(0编辑  收藏  举报