您的位置:首页 > 其它

POJ 3162 Walking Race(dfs+单调队列)

2012-09-20 16:58 127 查看
题意:对一棵树,求出从每个结点出发能到走的最长距离(每个结点最多只能经过一次),将这些距离按排成一个数组得到d[1],d[2],d[3]……d
,在数列的d中求一个最长的区间,使得区间中的最大值与最小值的差不超过m。

分析:用2次dfs能求出树的直径,对于树中任意结点,到树的直径的2个端点的距离的较大者即为最长距离。得到数组d后,用2个单调队列分别维护最大与最小值,扫描d数组,同时更新答案。

View Code

#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
#define N 1000001
int n,m,e;
int first
,next[N<<1],v[N<<1],w[N<<1];
int dx
,dy
,d
;
int qmin
,qmax
;
void init()
{
e=0;
memset(first+1,-1,sizeof(first[0])*n);
}
void add(int a,int b,int c)
{
v[e]=b;
w[e]=c;
next[e]=first[a];
first[a]=e++;
}
void dfs(int a,int fa,int dist,int *d)
{
int i,b;
for(i=first[a];~i;i=next[i])
{
b=v[i];
if(b^fa)    dfs(b,a,d[b]=dist+w[i],d);
}
}
void solve()
{
int i,j,front1,front2,rear1,rear2;
int ans=0;
front1=rear1=0;
front2=rear2=0;
for(i=1,j=1;j<=n;j++)
{
while(rear1>front1 && d[qmin[rear1-1]]>=d[j]) rear1--;
qmin[rear1++]=j;

while(rear2>front2 && d[qmax[rear2-1]]<=d[j]) rear2--;
qmax[rear2++]=j;

if(d[qmax[front2]]-d[qmin[front1]]>m)
{
ans=max(ans,j-i);
while(d[qmax[front2]]-d[qmin[front1]]>m)
{
i=min(qmin[front1],qmax[front2])+1;
while(front1<rear1&&qmin[front1]<i)   front1++;
while(front2<rear2&&qmax[front2]<i)   front2++;
}
}
}
ans=max(ans,j-i);
printf("%d\n",ans);
}
int main()
{
int i,a,b,c,x,y;
while(~scanf("%d%d",&n,&m))
{
init();
for(a=2;a<=n;a++)
{
scanf("%d%d",&b,&c);
add(a,b,c);
add(b,a,c);
}
dfs(1,0,dx[1]=0,dx);

for(x=1,i=2;i<=n;i++)
{
if(dx[i]>dx[x]) x=i;
}
dfs(x,0,dx[x]=0,dx);
for(y=1,i=2;i<=n;i++)
{
if(dx[i]>dx[y]) y=i;
}
dfs(y,0,dy[y]=0,dy);
for(int i=1;i<=n;i++)   d[i]=max(dx[i],dy[i]);
solve();
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: