• 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>




     
    
    
    
    
  • 相关阅读:
    高可用、高并发浅析
    正则表达式笔记
    linux下通过脚本切换当前工作目录
    nginx学习笔记
    二进制安全
    负载均衡相关
    有用的shell命令
    TCP服务器/客户端代码示例
    UDP服务器/客户端代码示例
    GCC链接的几个注意点
  • 原文地址:https://www.cnblogs.com/codeyuan/p/4254443.html
Copyright © 2020-2023  润新知