hdu 4607 (树形DP)

当时比赛的时候我们找出来只要求出树的最长的边的节点数ans,如果要访问点的个数n小于ans距离直接就是n-1

如果大于的话就是(n-ans)*2+ans-1,当时求树的直径难倒我们了,都不会树形dp

选一个点当根每次求出一点到子节点的最大距离和次大距离,两个的和最大的就是树的直径

还在网上看到一种方法,任意一点广搜达到最远点max,再从max广搜,到达最远点就是树的直径

自己想了想这种方法:如果中间有点有分支的话,那么这点的最大分支一定是到max的

但是它的次大分支就不一定是到起点的,所以从max搜的话肯定是到这点的次大分支,就是直径了



 

#include<stdio.h>

#include<string.h>

#define N 100001

int head[N],num,ins[N],n;

struct edge

{

    int ed,next;

}E[N*2];

void addedge(int x,int y)

{

    E[num].ed=y;

    E[num].next=head[x];

    head[x]=num++;

}

int dis;

int dist(int u)

{

    ins[u]=1;

    int max=0,mmax=0;

    for(int i=head[u];i!=-1;i=E[i].next)

    {

        int v=E[i].ed;

        if(ins[v]==1)continue;

        int temp=dist(v);

        if(temp>mmax)

        {

            max=mmax;

            mmax=temp;            

        }

        else if(temp>max)

        {

            max=temp;

        }

    }

    if(dis<(mmax+max+1))

        dis=mmax+max+1;

    return mmax+1;

}

int main()

{

    int i,m,x,y,t;

    scanf("%d",&t);

    while(t--)

    {

        scanf("%d%d",&n,&m);

        memset(head,-1,sizeof(head));

        num=0;

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

        {

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

            addedge(x,y);

            addedge(y,x);

        }

        memset(ins,0,sizeof(ins));

        dis=0;

        dist(1);

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

        {

            scanf("%d",&x);

            if(x<=dis)

                printf("%d\n",x-1);

            else printf("%d\n",dis+(x-dis)*2-1);

        }

    }

    return 0;

}


 


 

#include<stdio.h>

#include<queue>

#include<string.h>

#define N 100001

using namespace std;

int head[N],num,vis[N],n;

struct edge

{

    int ed,next;

}E[N*2];

struct node

{

	int x,w;

}cur,next;

void addedge(int x,int y)

{

    E[num].ed=y;

    E[num].next=head[x];

    head[x]=num++;

}

int dist()

{

	int i,v;

	memset(vis,0,sizeof(vis));

	queue<node>Q1,Q2;

	cur.x=1;

	Q1.push(cur);

	while(!Q1.empty())

	{

       cur=Q1.front();

	   Q1.pop();

	   vis[cur.x]=1;

	   for(i=head[cur.x];i!=-1;i=E[i].next)

	   {

		   next.x=v=E[i].ed;

		   if(vis[v]==0)

			   Q1.push(next);

	   }

	}

	cur.w=1;

	Q2.push(cur);//广搜最后出来的点一点是最远点

	memset(vis,0,sizeof(vis));

	while(!Q2.empty())

	{

		cur=Q2.front();

		Q2.pop();

		vis[cur.x]=1;

		for(i=head[cur.x];i!=-1;i=E[i].next)

		{

			next.x=v=E[i].ed;

			next.w=cur.w+1;

			if(vis[v]==0)

			  Q2.push(next);

		}

	}

	return cur.w;

}

int main()

{

    int i,m,x,y,t;

    scanf("%d",&t);

    while(t--)

    {

        scanf("%d%d",&n,&m);

        memset(head,-1,sizeof(head));

        num=0;

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

        {

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

            addedge(x,y);

            addedge(y,x);

        }

        int dis=dist();

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

        {

            scanf("%d",&x);

            if(x<=dis)

                printf("%d\n",x-1);

            else printf("%d\n",dis+(x-dis)*2-1);

        }

    }

    return 0;

}


 

 

你可能感兴趣的:(HDU)