poj 1986 Distance Queries

好像是模板题  当作练习题 不错;  要求任意两点之间的距离。可以假设一个根节点,然后所有点到根节点的距离,然后求出任意两点多公共祖先;  距离就变成了 

dis[u]+dis[v] - 2*dis[ lca(u,v) ]  非常好的题目  

 

 1 #include<iostream>
 2 #include<stdio.h>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<cmath>
 6 using namespace std;
 7 
 8 struct date{
 9    int v,val,next;
10 }edge[112345];
11 int N,M,total,head[112345],dis[112345];
12 void add_edge( int u,int v,int val ){
13    edge[total].v = v;
14    edge[total].val = val;
15    edge[total].next = head[u];
16    head[u] = total++;
17 }
18 bool vis[112345]; int num,sta[112345],tab[112345],dep[112345],dp[112345][22];
19 void LCA( int son,int deep,int w ){
20     dep[num] = deep; tab[num] = son; sta[son] = num++; dis[son] = w; vis[son] = true;
21     for( int i = head[son]; i != -1; i = edge[i].next ){
22        int v = edge[i].v; //cout<<edge[i].val<<endl;
23        if( !vis[v] )
24        { LCA( v,deep+1,w+edge[i].val ); dep[num] = deep; tab[num] = son; num++; }
25     }
26     //dep[num] = deep; tab[num] = son; num++;
27 }
28 int work( int n1,int n2 ){
29    if( dep[n1] < dep[n2] )return n1;
30    return n2;
31 }
32 void RMQ( ){
33     for( int i = 1; i <= num; i++ )dp[i][0] = i;
34     for( int i = 1; (1<<i) <= num; i++ )
35     for( int j = 1; j - 1 + (1<<i) <= num; j++ )
36         dp[j][i] = work( dp[j][i-1],dp[j+(1<<(i-1))][i-1] );
37 }
38 int query( int L,int R )
39 {
40     int k = 0;
41     while( (1<<(k+1)) <= (R-L+1) )k++;
42     return tab[work( dp[L][k],dp[R-(1<<k)+1][k] )];
43 }
44 int main( )
45 {
46     int u,v,w; char str[3];
47     while( scanf("%d%d",&N,&M) != EOF )
48     {
49          memset( head,-1,sizeof(head) ); total = 0;
50          for( int i = 1; i <= M; i++ )
51          {
52             scanf("%d%d%d%s",&u,&v,&w,&str);
53             add_edge( u,v,w );
54             add_edge( v,u,w );
55          }
56          memset( vis,0,sizeof(vis) );
57          num = 1; LCA( 1,1,0 ); num--; RMQ( );
58          //for( int i = 1; i <=  num; i++ )cout<<i<<" "<<dep[i]<<" "<<tab[i]<<endl;
59          int Q; scanf("%d",&Q);
60          while( Q-- ){
61             scanf("%d%d",&u,&v);
62             //cout<<u<<" "<<v<<" "<<dis[u]<<" "<<dis[v]<<endl;
63             if( sta[u] > sta[v] )swap( u,v );
64             int t = query(sta[u],sta[v]);//cout<<endl<<" "<<t<<endl;
65             //cout<<t<<" "<<dis[1]<<" "<<u<<" "<<v<<" "<<dis[u]<<" "<<dis[v]<<endl;
66             cout<<dis[u]+dis[v]-2*dis[t]<<endl;
67          }
68     }
69     return 0;
70 }
View Code

 

posted on 2013-10-03 19:51  浪舟  阅读(173)  评论(0编辑  收藏  举报

导航