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