HDU 3804 Query on a tree 非递归深搜 STL应用

题意:

 给定一颗树,边有权值,有q个查询,每次查询,x,y求1到x直接的所有不大于y的边的最大值.

题解:

 离线,先读入所有查询,再深度遍历这棵树,遍历到一条边就把边的权值扔到set里,返回的时候再把这条边的权值删掉.

 如果遍历到的当前点有询问,则对set进行upbounder,找到比当前y大的第一个位置,对迭代器--即可.

/* 

 * File:   main.cpp

 * Author: swordholy

 *

 * Created on 2011年3月30日, 下午2:00

 */

#include <cstdlib>

#include <iostream>

#include <stdio.h>

#include <memory.h>

#include <set>

#include <vector>

#include <stack>

#include <iterator>

using namespace std;

#define N 100005

struct res

{

    int i,x;

};

struct pt

{

    int p,v;

};

struct que

{

    int x,y,ans;

};

vector<pt> a[N];

vector<que> query;

vector<int> hasq[N];

stack<res> stk;

multiset<int> v;

multiset<int>::iterator it;

bool instack[N];

int iv[N];

int main(int argc, char** argv)

{

    int tcase,i,j,n,q,x,y,w;

    scanf("%d",&tcase);

    while(tcase--)

    {

        scanf("%d",&n);

        for(i=1;i<=n;i++)

            a[i].clear();

        iv[1]=-1;

        for(i=1;i<=n-1;i++)

        {

            scanf("%d%d%d",&x,&y,&w);

            iv[y]=w;

            pt temp;

            temp.p=y;

            temp.v=w;

            a[x].push_back(temp);

            temp.p=x;

            temp.v=w;

            a[y].push_back(temp);

        }

        scanf("%d",&q);

        for(i=1;i<=n;i++)

            hasq[i].clear();

        for(i=1;i<=q;i++)

            query.clear();

        for(i=1;i<=q;i++)

        {

            scanf("%d%d",&x,&y);

            que temp;

            temp.x=x;

            temp.y=y;

            temp.ans=-1;

            query.push_back(temp);

            hasq[x].push_back(query.size()-1);

        }

        v.clear();

        v.insert(-1);

        v.insert(-1);

        v.insert(-1);

        while(!stk.empty()) stk.pop();

        memset(instack,0,sizeof(instack));

        res temp;

        temp.x=1;

        temp.i=0;

        instack[1]=1;

        stk.push(temp);

        while(!stk.empty())

        {

            res now=stk.top();

            stk.pop();

            if (now.i==0)

            {

                if (hasq[now.x].size()>0)

                    for(int i=0;i<hasq[now.x].size();i++)

                    {

                        int qi=hasq[now.x][i];

                        int qx=query[qi].x;

                        int qy=query[qi].y;

                        int ans;

                        it=v.upper_bound(qy);

                        it--;

                        ans=(*it);

                        query[qi].ans=ans;

                    }

            }

            if (now.i==a[now.x].size()) {v.erase(v.find(iv[now.x]));continue;}   

            now.i++;

            stk.push(now);

            res next;

            next.i=0;

            next.x=a[now.x][now.i-1].p;

            if (!instack[next.x])

            {

              v.insert(a[now.x][now.i-1].v);

              stk.push(next);

              instack[next.x]=1;

            }

        }

        for(i=0;i<query.size();i++)

            printf("%d/n",query[i].ans);

    }

    return 0;

}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值