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;
}


 

 

posted on 2013-07-31 20:04  you Richer  阅读(192)  评论(0编辑  收藏  举报