hdoj 2586 How far away ?

原题:
How far away ?
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 10457 Accepted Submission(s): 3804

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

    #include <iostream>  
    #include <cstdio>  
    #include <cstring>  
    #include <queue>  
    #include <vector>  
    const int N = 44000;  
    #define INF 1000000000  
    using namespace std;  
    struct Node  
    {  
        int to,val;  
    };  
    vector<Node> v[N];  
    vector<int> query[N],num[N];  
    int ans[N];  
    bool vis[N];  
    int dis[N],father[N];  
    void isit(int n)  
    {  
        for(int i = 0;i<=n;i++)  
        {  
            v[i].clear();  
            query[i].clear();  
            num[i].clear();  
            vis[i] = false;  
            dis[i] = 0;  
            father[i] = i;  
        }  
    }  
    int find(int x)  
    {  
        if(x==father[x])  
            return x;  
        return father[x] = find(father[x]);  
    }  
    void Union(int x,int y)  
    {  
        x = find(x);  
        y = find(y);  
        if(x!=y)  
            father[y] = x; //让孩子节点指向父节点  
    }  
    void Tarjan(int o,int val)  
    {  
        vis[o] = true;  
        dis[o] = val;  
        for(int i = 0; i < v[o].size();i++)  
        {  
            Node tmp = v[o][i];  
            if(vis[tmp.to])  
                continue;  
            Tarjan(tmp.to,val+tmp.val);  
            Union(o,tmp.to);  
        }  
        for(int i=0;i<query[o].size();i++)  
        {  
            int tmp = query[o][i];  
            if(vis[tmp])  
                ans[num[o][i]] = dis[o] + dis[tmp] - 2*dis[find(tmp)];  
        }  
    }  
    int main()  
    {  
        int T;  
        scanf("%d",&T);  
        while(T--)  
        {  
            int n,m;  
            scanf("%d%d",&n,&m);  
            isit(n);  
            for(int i = 1;i < n; i++)  
            {  
                int x,y,z;  
                scanf("%d%d%d",&x,&y,&z);  
                v[x].push_back((Node){y,z});  
                v[y].push_back((Node){x,z});  
            }  
            for(int i=0;i<m;i++)  
            {  
                int x,y;  
                scanf("%d%d",&x,&y);  
                query[x].push_back(y);  
                num[x].push_back(i);  
                query[y].push_back(x);  
                num[y].push_back(i);  
            }  
            Tarjan(1,0);  
            for(int i = 0;i<m;i++)  
                printf("%d\n",ans[i]);  
        }  
        return 0;  
    }  

解答:
我做这道题的时候是用最短路径,结果肯定是超时。
后来知道要用最近公共祖先算法。借鉴了这位朋友代码,觉得挺好理解的,所以转载了。

原帖地址:http://blog.csdn.net/y990041769/article/details/40856001

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值