POJ 3162 Walking Race 树的直径+线段树

来源:互联网 发布:制作毕业视频软件 编辑:程序博客网 时间:2024/06/06 00:53

题目链接

http://poj.org/problem?id=3162

题意

给定一颗含n个结点的树,求每个点能走到的最远距离,挑选连续的k天 最长与最短之差不超过m,求最大k

思路

先求树的直径,然后线段树维护

#include<cstdio>#include<iostream>#include<algorithm>#include<cstring>#include<vector>#include<string>#include<queue>#include<stack>#include<math.h>#include<set>#include<map>#define ll long longusing namespace std;const int INF = ( 2e9 ) + 2;const ll maxn = 1e6+10;struct edge{    int v,w,next;} e[maxn*2];struct node{    int Max,Min;    int l,r;}t[maxn*4];int head[maxn];int tot;int d[2][maxn],Max[maxn];bool vis[maxn];int n,m;void build(int root,int l,int r){    t[root].l=l;    t[root].r=r;    if(l==r)    {        t[root].Max=t[root].Min=Max[l];        return;    }    int mid=(l+r)>>1;    build(2*root,l,mid);    build(2*root+1,mid+1,r);    t[root].Max=max(t[root*2].Max,t[root*2+1].Max);    t[root].Min=min(t[root*2].Min,t[root*2+1].Min);}int query(int root,int ql,int qr,bool mode){    int l=t[root].l,r=t[root].r;    if(l>=ql&&r<=qr)    {        if(mode)return t[root].Max;        else return t[root].Min;    }    if(l>qr||r<ql)return 0;    int mid = (l+r)>>1;    if(qr<=mid)    return query(2*root,ql,qr,mode);    else if(ql>mid)    return query(2*root+1,ql,qr,mode);    else    {        if(mode)        return max(query(2*root,ql,qr,mode),query(2*root+1,ql,qr,mode));        else        return min(query(2*root,ql,qr,mode),query(2*root+1,ql,qr,mode));    }}void init(){    memset(head,-1,sizeof(head));    memset(vis,0,sizeof(vis));    tot=0;    d[0][1]=0;}void add(int u,int v,int w){    e[tot].v=v;    e[tot].w=w;    e[tot].next=head[u];    head[u]=tot++;}// 连续的k天 最长与最短之差不超过mvoid dfs(int u,int *d){    vis[u]=true;    for(int i=head[u]; i!=-1; i=e[i].next)    {        int v=e[i].v,w=e[i].w;        if(vis[v])continue;        d[v]=d[u]+w;        dfs(v,d);    }}int solve(){    dfs(1,d[0]);    int mx=-INF,pos;    memset(vis,0,sizeof(vis));    for(int i=1; i<=n; i++)        if(mx<d[0][i])        {            mx=d[0][i];            pos=i;        }    d[0][pos]=0;    memset(vis,0,sizeof(vis));    dfs(pos,d[0]);    mx=-INF;    for(int i=1;i<=n;i++)        if(mx<d[0][i])        {            mx=d[0][i];            pos=i;        }    d[1][pos]=0;    memset(vis,0,sizeof(vis));    dfs(pos,d[1]);    for(int i=1;i<=n;i++)    Max[i]=max(d[0][i],d[1][i]);    build(1,1,n);    int i=1,j=1;    int ans=-INF;    for(;j<=n;j++)    {        while(query(1,i,j,1)-query(1,i,j,0)>m)i++;        ans=max(ans,j-i+1);    }    return ans;}int main(){    int u,v,w;    while(~scanf("%d%d",&n,&m))    {        init();        for(int i=2; i<=n; i++)        {            scanf("%d%d",&v,&w);            add(i,v,w);            add(v,i,w);        }        printf("%d\n",solve());    }}
阅读全文
0 0
原创粉丝点击