POJ 1986 DIstance Query LCA水题

给出一棵树,对于每一个询问,给出2个节点,输出2个节点的距离。

输入中有字母,那个是没有用的,不用管。

 

思路:

0.选择编号为1的节点作为树的root

(注意:有些题的边是单向的,这时候我们要根据节点的入度来确定root,

    双向的话一般可以随意选择一个节点作为root)

 

1.dfs1,求出dep和pa[i][0]

2.初始化数组pa

3.节点(u,v)的权值为w

 把本来是边的权值w赋给u,v中dep较大的节点,

 cost[i]表示节点i的权值为cost[i]

 先初始化:cost[root]=0

4.dfs2,求每一个节点到root的距离dis[i]

5.查询:dis(u,v)=dis[u]+dis[v]-2*dis[lca(u,v)];

 

 

 

  1 #include<cstdio>
  2 #include<cstring>
  3 
  4 using namespace std;
  5 
  6 const int maxn=40000+5;
  7 const int inf=0x3f3f3f3f;
  8 
  9 inline int swap(int &x,int &y)
 10 {
 11     x^=y;
 12     y^=x;
 13     x^=y;
 14 }
 15 
 16 struct Edge
 17 {
 18     int to,next;
 19 };
 20 Edge edge[maxn<<1];
 21 int head[maxn];
 22 int tot=0;
 23 int cost[maxn];
 24 int dis[maxn];
 25 int pa[maxn][17];
 26 int dep[maxn];
 27 int e[maxn][3];
 28 
 29 void init()
 30 {
 31     memset(head,-1,sizeof head);
 32     tot=1;
 33     memset(dep,0,sizeof dep);
 34     memset(pa,-1,sizeof pa);
 35 }
 36 
 37 void addedge(int u,int v)
 38 {
 39     edge[tot].to=v;
 40     edge[tot].next=head[u];
 41     head[u]=tot++;
 42 }
 43 
 44 void dfs1(int u)
 45 {
 46     for(int i=head[u];~i;i=edge[i].next)
 47     {
 48         int v=edge[i].to;
 49         if(!dep[v])
 50         {
 51             dep[v]=dep[u]+1;
 52             pa[v][0]=u;
 53             dfs1(v);
 54         }
 55     }
 56 }
 57 
 58 void init_pa(int n)
 59 {
 60     for(int j=1;(1<<j)<=n;j++)
 61     {
 62         for(int i=1;i<=n;i++)
 63         {
 64             if(pa[i][j-1]!=-1)
 65                 pa[i][j]=pa[pa[i][j-1]][j-1];
 66         }
 67     }
 68 }
 69 
 70 void dfs2(int u,int pre)
 71 {
 72     for(int i=head[u];~i;i=edge[i].next)
 73     {
 74         int v=edge[i].to;
 75         if(v==pre)
 76             continue;
 77         dis[v]=dis[u]+cost[v];
 78         dfs2(v,u);
 79     }
 80 }
 81 
 82 int query(int a,int b,int n)
 83 {
 84     int init_a=a;
 85     int init_b=b;
 86     if(dep[a]<dep[b])
 87         swap(a,b);
 88     int cnt;
 89     for(cnt=0;dep[a]-(1<<cnt)>=0;cnt++)
 90         ;
 91     cnt--;
 92     for(int j=cnt;j>=0;j--)
 93     {
 94         if(dep[a]-(1<<j)>=dep[b])
 95             a=pa[a][j];
 96     }
 97     if(a==b)
 98         return dis[init_a]+dis[init_b]-2*dis[a];
 99     for(int i=cnt;i>=0;i--)
100     {
101         if(pa[a][i]!=-1&&pa[a][i]!=pa[b][i])
102         {
103             a=pa[a][i];
104             b=pa[b][i];
105         }
106     }
107     return dis[init_a]+dis[init_b]-2*dis[pa[a][0]];
108 }
109 
110 void solve(int n)
111 {
112     dep[1]=1;
113     dfs1(1);
114     init_pa(n);
115     cost[1]=0;
116     dis[1]=0;
117     for(int i=1;i<=n;i++)
118     {
119         if(dep[e[i][0]]>dep[e[i][1]])
120             swap(e[i][0],e[i][1]);
121         cost[e[i][1]]=e[i][2];
122     }
123     dfs2(1,-1);
124 
125     int m;
126     scanf("%d",&m);
127     for(int i=1;i<=m;i++)
128     {
129         int u,v;
130         scanf("%d%d",&u,&v);
131         printf("%d\n",query(u,v,n));
132     }
133     return ;
134 }
135 
136 int main()
137 {
138     int n;
139     while(~scanf("%d",&n))
140     {
141         init();
142         int m;
143         scanf("%d",&m);
144         for(int i=1;i<=m;i++)
145         {
146             int u,v,w;
147             char ch;
148             scanf("%d %d %d %c",&e[i][0],&e[i][1],&e[i][2],&ch);
149             addedge(e[i][0],e[i][1]);
150             addedge(e[i][1],e[i][0]);
151         }
152         solve(n);
153     }
154     return 0;
155 }
View Code

 

转载于:https://www.cnblogs.com/-maybe/p/4739571.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值