LCA和RMQ题目汇总


 1.HDU 3183

<span style="color:#000099;">A Magic Lamp
Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 1624    Accepted Submission(s): 628


Problem Description
Kiki likes traveling. One day she finds a magic lamp, unfortunately the genie in the lamp is not so kind. Kiki must answer a question, and then the genie will realize one of her dreams. 
The question is: give you an integer, you are allowed to delete exactly m digits. The left digits will form a new integer. You should make it minimum.
You are not allowed to change the order of the digits. Now can you help Kiki to realize her dream?

 

Input
There are several test cases.
Each test case will contain an integer you are given (which may at most contains 1000 digits.) and the integer m (if the integer contains n digits, m will not bigger then n). The given integer will not contain leading zero.

 

Output
For each case, output the minimum result you can get in one line.
If the result contains leading zero, ignore it. 

 

Sample Input
178543 4 
1000001 1
100001 2
12345 2
54321 2
 

Sample Output
13
1
0
123
321
 

Source
HDU 2009-11 Programming Contest </span>
<span style="color:#000099;"></span> 
<span style="color:#000099;">/*********************************
     author   : Grant Yuan
     time     : 2014/08/23 13:23:48
     algorithm: RMQ
     source   : HDU 3183
**********************************/
#include<stdio.h>
#include<string.h>
#include<math.h>
#define N 1005

int m,n;
char a[N];
char num[N];
int f[N][N];
int min(int i,int j)
{
    return a[i]<=a[j] ? i:j;
}

void ST()
{
    int i,j;
    for(i=0;i<n;i++)
       f[i][0]=i;
    for(j=1;j<=(int)(log((double)n)/log(2.0));j++)
    {
        for(i=0;i+(1<<j)-1<n;i++)
           f[i][j]=min(f[i][j-1],f[i+(1<<(j-1))][j-1]);
    }
}

int query(int L,int R)
{
    int x=(int)(log(double(R-L+1))/log(2.0));
    return min(f[L][x],f[R-(1<<x)+1][x]);
}

int main()
{
    int i,j,L,R;
    while(~scanf("%s%d",a,&m)){
        int len=strlen(a); n=len;
        m=len-m;ST();
        i=j=0;
        while(m--){
            i=query(i,len-m-1);
            num[j++]=a[i++];
        }
         for(i=0;i<j;i++)
        {
            if(num[i]!='0')
               break;
        }
         if(i==j)
        {
            puts("0");
            continue;
        }
        while(i<j)
        {
            printf("%c",num[i]);
            i++;
        }
        puts("");

    }
    return 0;
}
</span>
<span style="color:#000099;">
</span> 
<span style="color:#000099;">2.HDU 3486</span>
<span style="color:#000099;">Interviewe
Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 5296    Accepted Submission(s): 1240


Problem Description
YaoYao has a company and he wants to employ m people recently. Since his company is so famous, there are n people coming for the interview. However, YaoYao is so busy that he has no time to interview them by himself. So he decides to select exact m interviewers for this task.
YaoYao decides to make the interview as follows. First he queues the interviewees according to their coming order. Then he cuts the queue into m segments. The length of each segment is , which means he ignores the rest interviewees (poor guys because they comes late). Then, each segment is assigned to an interviewer and the interviewer chooses the best one from them as the employee.
YaoYao’s idea seems to be wonderful, but he meets another problem. He values the ability of the ith arrived interviewee as a number from 0 to 1000. Of course, the better one is, the higher ability value one has. He wants his employees good enough, so the sum of the ability values of his employees must exceed his target k (exceed means strictly large than). On the other hand, he wants to employ as less people as possible because of the high salary nowadays. Could you help him to find the smallest m?

 

Input
The input consists of multiple cases.
In the first line of each case, there are two numbers n and k, indicating the number of the original people and the sum of the ability values of employees YaoYao wants to hire (n≤200000, k≤1000000000). In the second line, there are n numbers v1, v2, …, vn (each number is between 0 and 1000), indicating the ability value of each arrived interviewee respectively.
The input ends up with two negative numbers, which should not be processed as a case.

 

Output
For each test case, print only one number indicating the smallest m you can find. If you can’t find any, output -1 instead.
 

Sample Input
11 300
7 100 7 101 100 100 9 100 100 110 110
-1 -1
 

Sample Output
3
HintWe need 3 interviewers to help YaoYao. The first one interviews people from 1 to 3, the second interviews people from 4 to 6, 
and the third interviews people from 7 to 9. And the people left will be ignored. And the total value you can get is 100+101+100=301>300. 
 

Source
2010 ACM-ICPC Multi-University Training Contest(5)——Host by BJTU </span>
<span style="color:#000099;"> 
</span>
<span style="color:#000099;">/*********************************
     author   : Grant Yuan
     time     : 2014-08-24 11:54:38
     algorithm: RMQ
     source   : HDU 3486
**********************************/
#include<algorithm>
#include<iostream>
#include<cstdio>
#include<cstring>
#include<map>
#include<queue>
#include<deque>
#include<set>
#include<cstdlib>
#include<stack>
#include<cmath>

#define INF 0x7fffffff
#define LL long long
#define mem(a) memset(a,0,sizeof(a))
#define memm(a) memset(a,1,sizeof(a))
#define rep(i,n) for(int i=0;i<n;i++)
#define repp(i,m,n) for(int i=m;i<=n;i++)
#define scd(a) scanf("%d",&a)
#define scld(a) scanf("%I64d",&a)
#define scldd(a,b) scanf("%I64d%I64d",&a,&b)
#define sclddd(a,b,c) scanf("%I64d%64d",&a,&b,&c)
#define prd(a) printf("%d
",(int)a)
#define scf(a) scanf("%lf",&a)
#define scs(a) scanf("%s",&s)
#define scdd(a,b) scanf("%d%d",&a,&b)
#define prdd(a,b) printf("%d %d
",(int)a,(int)b)
#define scddd(a,b,c) scanf("%d%d%d",&a,&b,&c)
#define prddd(a,b,c) printf("%d %d %d
",(int)a,(int)b,(int)c)
#define scff(a,b) scanf("%lf%lf",&a,&b,&c)
#define scfff(a,b,c) scanf("%lf%lf%lf",&a,&b,&c)
#define MAX 200007
#define eps 1e-8

using namespace std;
int n,k,sum;
int a[MAX],dp[MAX][20],ans2;
bool flag;

int max(int i,int j)
{
    return i>=j?i:j;
}

void build_st()
{
    int i,j,temp;
    temp=(int)(log(n*1.0)/log(2.0));
    repp(i,1,n) dp[i][0]=a[i];
     for(j=1;j<=(int)(log(n*1.0)/log(2.0));j++)
    {
        for(i=1;i+(1<<j)-1<=n;i++)
           dp[i][j]=max(dp[i][j-1],dp[i+(1<<(j-1))][j-1]);
    }
}

int query(int l,int r)
{
    int temp=(int)(log((r-l+1)*1.0)/log(2.0));
    return max(dp[l][temp],dp[r-(1<<temp)+1][temp]);
}

inline bool can(int mid)
{
    int ans1=0;
    int r=mid;
    int i=0,j=i+r-1;
    ans2=0;
    while(j<n){
        ans2++;
        int t=query(i,j);
        ans1+=a[t];
        if(ans1>k) break;
        i=j+1;j=i+r-1;
    }
    if(ans1>k) return true;
    return false;
}

int main()
{
    LL sum=0;
    while(1){
        scdd(n,k);int minr=INF;LL ans=INF;
        if(n<0) break;
        mem(a);mem(dp);
        repp(i,1,n) {scd(a[i]);sum+=a[i];minr=min(minr,a[i]);}
        if(sum<k) {printf("-1
"); continue;}
        if(k<=minr) {printf("1
");continue;}
        build_st();
        int i;
        int pre = -1;int len,m,aa,bb,temp;
        for (i = 1; i <= n; ++i) {
            len = n / i;
            m = len*i;
            if (len != pre) {
                aa = 1;
                bb = len;
                ans = 0;
            } else {
                aa = temp + 1;
                bb = temp + len;
            }
            while (bb <= m) {
                ans += query(aa, bb);
                aa += len;
                bb += len;
            }
            if (ans > k)
                break;
            pre = len;
            temp=m;

        }

           if (i > n)
            printf("-1
");
        else
            printf("%d
", i);


    }
    return 0;}</span>
<span style="color:#000099;">3. POJ 3264</span>
<span style="color:#000099;"></span> 
<span style="color:#000099;">Balanced Lineup
Time Limit: 5000MS  Memory Limit: 65536K 
Total Submissions: 34790  Accepted: 16382 
Case Time Limit: 2000MS 

Description

For the daily milking, Farmer John's N cows (1 ≤ N ≤ 50,000) always line up in the same order. One day Farmer John decides to organize a game of Ultimate Frisbee with some of the cows. To keep things simple, he will take a contiguous range of cows from the milking lineup to play the game. However, for all the cows to have fun they should not differ too much in height.

Farmer John has made a list of Q (1 ≤ Q ≤ 200,000) potential groups of cows and their heights (1 ≤ height ≤ 1,000,000). For each group, he wants your help to determine the difference in height between the shortest and the tallest cow in the group.

Input

Line 1: Two space-separated integers, N and Q. 
Lines 2..N+1: Line i+1 contains a single integer that is the height of cow i 
Lines N+2..N+Q+1: Two integers A and B (1 ≤ A ≤ B ≤ N), representing the range of cows from A to B inclusive.
Output

Lines 1..Q: Each line contains a single integer that is a response to a reply and indicates the difference in height between the tallest and shortest cow in the range.
Sample Input

6 3
1
7
3
4
2
5
1 5
4 6
2 2
Sample Output

6
3
0
Source

USACO 2007 January Silver 
</span>
<span style="color:#000099;">/*********************************
     author   : Grant Yuan
     time     : 2014-08-24 23:49:38
     algorithm: RMQ
     source   : POJ 3264
**********************************/
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#define INF 0x7fffffff
#define MAX 50007

using namespace std;

struct node
{
    int mmin;
    int mmax;
};
int a[MAX];
node dp[MAX][20];
int n,m;

void Build_St()
{
    int t=(int)(log((n+1)*1.0)/log(2.0));
    for(int i=1;i<=n;i++) dp[i][0].mmin=dp[i][0].mmax=a[i];
    for(int j=1;j<=t;j++)
        for(int i=1;i+(1<<j)-1<=n;i++)
    {
        dp[i][j].mmin=min(dp[i][j-1].mmin,dp[i+(1<<(j-1))][j-1].mmin);
        dp[i][j].mmax=max(dp[i][j-1].mmax,dp[i+(1<<(j-1))][j-1].mmax);
    }
}

int Query_Min(int L,int R)
{
   int t=(int)(log((R-L+1)*1.0)/log(2.0));
   return min(dp[L][t].mmin,dp[R-(1<<t)+1][t].mmin);
}

int Query_Max(int L,int R)
{
  int t=(int)(log((R-L+1)*1.0)/log(2.0));
   return max(dp[L][t].mmax,dp[R-(1<<t)+1][t].mmax);
}

int main()
{
    while(~scanf("%d%d",&n,&m))
    {
        //int t;
        memset(a,0,sizeof(a));
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&a[i]);
        }
        Build_St();
        int l,r;
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d",&l,&r);
            int ans1=Query_Max(l,r);
            int ans2=Query_Min(l,r);
            printf("%d
",ans1-ans2);
        }
    }
    return 0;
}
</span>
<span style="color:#000099;">
</span> 
<span style="color:#000099;">4.POJ 1330</span>
<span style="color:#000099;">Nearest Common Ancestors
Time Limit: 1000MS  Memory Limit: 10000K 
Total Submissions: 18569  Accepted: 9845 

Description

A rooted tree is a well-known data structure in computer science and engineering. An example is shown below: 

 
In the figure, each node is labeled with an integer from {1, 2,...,16}. Node 8 is the root of the tree. Node x is an ancestor of node y if node x is in the path between the root and node y. For example, node 4 is an ancestor of node 16. Node 10 is also an ancestor of node 16. As a matter of fact, nodes 8, 4, 10, and 16 are the ancestors of node 16. Remember that a node is an ancestor of itself. Nodes 8, 4, 6, and 7 are the ancestors of node 7. A node x is called a common ancestor of two different nodes y and z if node x is an ancestor of node y and an ancestor of node z. Thus, nodes 8 and 4 are the common ancestors of nodes 16 and 7. A node x is called the nearest common ancestor of nodes y and z if x is a common ancestor of y and z and nearest to y and z among their common ancestors. Hence, the nearest common ancestor of nodes 16 and 7 is node 4. Node 4 is nearer to nodes 16 and 7 than node 8 is. 

For other examples, the nearest common ancestor of nodes 2 and 3 is node 10, the nearest common ancestor of nodes 6 and 13 is node 8, and the nearest common ancestor of nodes 4 and 12 is node 4. In the last example, if y is an ancestor of z, then the nearest common ancestor of y and z is y. 

Write a program that finds the nearest common ancestor of two distinct nodes in a tree. 


Input

The input consists of T test cases. The number of test cases (T) is given in the first line of the input file. Each test case starts with a line containing an integer N , the number of nodes in a tree, 2<=N<=10,000. The nodes are labeled with integers 1, 2,..., N. Each of the next N -1 lines contains a pair of integers that represent an edge --the first integer is the parent node of the second integer. Note that a tree with N nodes has exactly N - 1 edges. The last line of each test case contains two distinct integers whose nearest common ancestor is to be computed. 
Output

Print exactly one line for each test case. The line should contain the integer that is the nearest common ancestor. 
Sample Input

2
16
1 14
8 5
10 16
5 9
4 6
8 4
4 10
1 13
6 15
10 11
6 7
10 2
16 3
8 1
16 12
16 7
5
2 3
3 4
3 1
1 5
3 5

Sample Output

4
3


Source

Taejon 2002</span>
<span style="color:#000099;">/*********************************
     author   : Grant Yuan
     time     : 2014-08-25 01:57:22
     algorithm: LCA
     source   : POJ 1330
**********************************/
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<vector>
#include<cmath>
#include<algorithm>
#define INF 0x7fffffff
#define MAX 10007
#define N (int)log(MAX*1.0)+1

using namespace std;
int depth[MAX],parent[30][MAX];
int root,t,n,m;
int MaxLog;
vector<int> G[MAX];

void dfs(int v,int p,int d)
{
    depth[v]=d;
    parent[0][v]=p;
    for(int i=0;i<G[v].size();i++)
    {
        if(G[v][i]!=p) dfs(G[v][i],v,d+1);
    }
}

void init(int V)
{
    dfs(root,-1,0);
    for(int k=0;k+1<MaxLog;k++)
    {
          for(int v=0;v<V;v++)
          {
              if(parent[k][v]<0) parent[k+1][v]=-1;
              else parent[k+1][v]=parent[k][parent[k][v]];
          }
    }

}

int Lca(int u,int v)
{
    while(depth[u]>depth[v]) u=parent[0][u];
    while(depth[v]>depth[u]) v=parent[0][v];
    while(u!=v){
        u=parent[0][u];
        v=parent[0][v];
    }
    return u;
}
int main()
{
    scanf("%d",&t);
    while(t--){
        scanf("%d",&n);
        for(int i=0;i<MAX;i++)
            while(!G[i].empty()) G[i].clear();
        memset(parent,-1,sizeof(parent));
        memset(depth,0,sizeof(depth));
        MaxLog=floor(log(n*1.0)/log(2.0));

        for(int i=1;i<n;i++)
        {
            int a,b;
            scanf("%d%d",&a,&b);
            parent[0][b]=a;
            G[a].push_back(b);
        }
        for(int i=1;i<=n;i++) {if(parent[0][i]==-1) {root=i;break;}}
        init(n);
        int u,v;
        scanf("%d%d",&u,&v);
        int ans=Lca(u,v);
        printf("%d
",ans);
    }
    return 0;
}
</span>

 

<span style="color:#000099;">5.POJ 1470</span>
<span style="color:#000099;">Closest Common Ancestors
Time Limit: 2000MS  Memory Limit: 10000K 
Total Submissions: 15444  Accepted: 4942 

Description

Write a program that takes as input a rooted tree and a list of pairs of vertices. For each pair (u,v) the program determines the closest common ancestor of u and v in the tree. The closest common ancestor of two nodes u and v is the node w that is an ancestor of both u and v and has the greatest depth in the tree. A node can be its own ancestor (for example in Figure 1 the ancestors of node 2 are 2 and 5)
Input

The data set, which is read from a the std input, starts with the tree description, in the form: 

nr_of_vertices 
vertex:(nr_of_successors) successor1 successor2 ... successorn 
... 
where vertices are represented as integers from 1 to n ( n <= 900 ). The tree description is followed by a list of pairs of vertices, in the form: 
nr_of_pairs 
(u v) (x y) ... 

The input file contents several data sets (at least one). 
Note that white-spaces (tabs, spaces and line breaks) can be used freely in the input.
Output

For each common ancestor the program prints the ancestor and the number of pair for which it is an ancestor. The results are printed on the standard output on separate lines, in to the ascending order of the vertices, in the format: ancestor:times 
For example, for the following tree: 


Sample Input

5
5:(3) 1 4 2
1:(0)
4:(0)
2:(1) 3
3:(0)
6
(1 5) (1 4) (4 2)
      (2 3)
(1 3) (4 3)
Sample Output

2:1
5:5
Hint

Huge input, scanf is recommended.
Source

Southeastern Europe 2000</span>
<span style="color:#000099;">/*********************************
     author   : Grant Yuan
     time     : 2014-08-25 16:46:12
     algorithm: LCA
     source   : POJ 1470
**********************************/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<vector>
#define MAX 1007

using namespace std;
int n,m,t,root;
int parent[MAX],depth[MAX],fre[MAX];
vector<int> G[MAX];
bool flag[MAX];
void dfs(int v,int p,int d)
{
    parent[v]=p;
    depth[v]=d;
    for(int i=0;i<G[v].size();i++)
    {
        if(G[v][i]!=p) dfs(G[v][i],v,d+1);
    }
}

void init()
{
   for(int i=1;i<=n;i++) if(flag[i]==0){root=i;break;}
   dfs(root,-1,0);
}

int lca(int u,int v)
{
    while(depth[u]>depth[v]) u=parent[u];
    while(depth[v]>depth[u]) v=parent[v];
    while(u!=v){u=parent[u];v=parent[v];}
    return u;
}


int main()
{
    while(~scanf("%d",&n)){
        memset(parent,-1,sizeof(parent));
        memset(fre,0,sizeof(fre));
        memset(flag,0,sizeof(flag));
        memset(depth,0,sizeof(depth));
        for(int i=0;i<MAX;i++) G[i].clear();
        int v,m,u;
        for(int k=1;k<=n;k++){
          scanf("%d:(%d)",&v,&m);
          for(int i=1;i<=m;i++)
          {
            int u;
            scanf("%d",&u);
            flag[u]=1;
            G[v].push_back(u);
          }
        }
        init();
        scanf("%d",&m);
        for(int i=1;i<=m;i++)
        {
            scanf(" (%d %d)",&v,&u);
            int croot=lca(v,u);
            fre[croot]++;
        }
        for(int i=1;i<=n;i++)
        {
            if(fre[i]) printf("%d:%d
",i,fre[i]);
        }
    }
    return 0;
}

</span>
<span style="color:#000099;">6.POJ 1986
</span>
<span style="color:#000099;">Distance Queries
Time Limit: 2000MS  Memory Limit: 30000K 
Total Submissions: 9411  Accepted: 3296 
Case Time Limit: 1000MS 

Description

Farmer John's cows refused to run in his marathon since he chose a path much too long for their leisurely lifestyle. He therefore wants to find a path of a more reasonable length. The input to this problem consists of the same input as in "Navigation Nightmare",followed by a line containing a single integer K, followed by K "distance queries". Each distance query is a line of input containing two integers, giving the numbers of two farms between which FJ is interested in computing distance (measured in the length of the roads along the path between the two farms). Please answer FJ's distance queries as quickly as possible! 

Input

* Lines 1..1+M: Same format as "Navigation Nightmare" 

* Line 2+M: A single integer, K. 1 <= K <= 10,000 

* Lines 3+M..2+M+K: Each line corresponds to a distance query and contains the indices of two farms. 

Output

* Lines 1..K: For each distance query, output on a single line an integer giving the appropriate distance. 

Sample Input

7 6
1 6 13 E
6 3 9 E
3 5 7 S
4 1 3 N
2 4 20 W
4 7 2 S
3
1 6
1 4
2 6

Sample Output

13
3
36

Hint

Farms 2 and 6 are 20+3+13=36 apart. 

Source

USACO 2004 February</span>
<span style="color:#000099;">/*********************************
     author   : Grant Yuan
     time     : 2014-08-26 17:50:13
     algorithm: LCA
     source   : POJ 1986
**********************************/
#include<set>
#include<queue>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int N = 100010;
#define For(i,n) for(int i=1;i<=n;i++)
#define Rep(i,l,r) for(int i=l;i<=r;i++)

struct Edge{
     int t,next,w;
 }E[N*2];
vector< pair<int,int> > Q[N];
int s,t,w,Es,ans[N],head[N],fa[N],d[N];
bool vis[N];

 int find(int i){
     if(fa[i]==i) return i;
     else         return find(fa[i]);
 }

 void makelist(int s,int t,int w){
     E[Es].t = t; E[Es].w = w;E[Es].next = head[s];
     head[s] = Es++;
 }

 void LCA(int i,int w){
     d[i] = w;fa[i] = i;
    vis[i] = true;
     for(int p=head[i];p!=-1;p=E[p].next)
         if(!vis[E[p].t]){
                    LCA(E[p].t,w+E[p].w);
            fa[E[p].t] = i;
         }
     int  len = Q[i].size();
     for(int j=0;j<len;j++){
         if(vis[Q[i][j].first])
             ans[Q[i][j].second] = w + d[Q[i][j].first] - 2 * d[find(Q[i][j].first)];
     }
 }
 int n,m,qn;
 int main(){
     memset(head,-1,sizeof(head));
     scanf("%d%d",&n,&m);
     For(i,m){
        scanf("%d%d%d %*c",&s,&t,&w);
         makelist(s,t,w);makelist(t,s,w);
     }
     scanf("%d",&qn);
     For(i,qn){
         scanf("%d%d",&s,&t);
         Q[s].push_back(make_pair(t,i));Q[t].push_back(make_pair(s,i));
     }
     LCA(1,0);
     For(i,qn) printf("%d
",ans[i]);
     return 0;
 }


</span>
<span style="color:#000099;">7.HDU 2586</span>
<span style="color:#000099;">How far away ?
Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 5471    Accepted Submission(s): 2077


Problem Description
There are n houses in the village and some bidirectional roads connecting them. Every day peole always like to ask like this "How far is it if I want to go from house A to house B"? Usually it hard to answer. But luckily int this village the answer is always unique, since the roads are built in the way that there is a unique simple path("simple" means you can't visit a place twice) between every two houses. Yout task is to answer all these curious people.
 

Input
First line is a single integer T(T<=10), indicating the number of test cases.
  For each test case,in the first line there are two numbers n(2<=n<=40000) and m (1<=m<=200),the number of houses and the number of queries. The following n-1 lines each consisting three numbers i,j,k, separated bu a single space, meaning that there is a road connecting house i and house j,with length k(0<k<=40000).The houses are labeled from 1 to n.
  Next m lines each has distinct integers i and j, you areato answer the distance between house i and house j.
 

Output
For each test case,output m lines. Each line represents the answer of the query. Output a bland line after each test case.
 

Sample Input
2
3 2
1 2 10
3 1 15
1 2
2 3

2 2
1 2 100
1 2
2 1
 

Sample Output
10
25
100
100
 

Source
ECJTU 2009 Spring Contest 
</span>
<pre class="cpp" name="code"><span style="color:#000099;">/*********************************
     author   : Grant Yuan
     time     : 2014-08-25 20:54:16
     algorithm: LCA
     source   : HDU 2586
**********************************/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<vector>
#define MAX 100007

using namespace std;
int n,m,t,root;
int parent[MAX],depth[MAX],dis[MAX],disroot[MAX];

struct node
{
    int id;
    int far;
};
vector<node> G[MAX];
node s[MAX*100];
int base,top,ans;
bool flag[MAX];
void bfs(int u,int v)
{
    while(top>base){
        if(s[base].id==v){
            ans=s[base].far;
            return;
        }
     int m=s[base].id;int l=s[base].far;
     for(int i=0;i<G[m].size();i++)
     {
          if(!flag[G[m][i].id]){
                flag[G[m][i].id]=1;
            s[top].id=G[m][i].id;
            s[top++].far=l+G[m][i].far;
          }
     }
     base++;
    }
}

int main()
{
    int t;
    scanf("%d",&t);
    int q;
    while(t--){
        scanf("%d%d",&n,&q);
        memset(parent,-1,sizeof(parent));
        memset(disroot,0,sizeof(disroot));
        memset(depth,0,sizeof(depth));
        memset(dis,0,sizeof(dis));
        for(int i=0;i<MAX;i++) G[i].clear();
        node p;
        for(int i=1;i<n;i++)
        {
            int a,b,l;
            scanf("%d%d%d",&a,&b,&l);
            p.id=b;p.far=l;
            G[a].push_back(p);
            p.id=a;
            G[b].push_back(p);
        }
        int u,v;
        for(int i=1;i<=q;i++)
        {  memset(flag,0,sizeof(flag));
            scanf("%d%d",&u,&v);
            top=base=0;
             s[top].id=u;s[top].far=0;
             top++;
            bfs(u,v);
            printf("%d
",ans);

        }
    }
    return 0;
}


</span>




 



原文地址:https://www.cnblogs.com/codeyuan/p/4254443.html