• 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
    ",x-1);
                else printf("%d
    ",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
    ",x-1);
                else printf("%d
    ",dis+(x-dis)*2-1);
            }
        }
        return 0;
    }


  • 相关阅读:
    操作系统简介
    正则表达式
    Python socket
    计算机网络基础
    计算机基础
    Python常用模块
    Python模块和包
    Python反射和内置方法(双下方法)
    Python类的成员
    更改命令行,完全显示hostname
  • 原文地址:https://www.cnblogs.com/riskyer/p/3228610.html
Copyright © 2020-2023  润新知