标签:
树的直径是指树的最长简单路。
求法: 两遍BFS/DFS :
先任选一个起点BFS找到最长路的终点,再从终点进行BFS,则第二次BFS找到的最长路即为树的直径;
原理: 设起点为u,第一次BFS/DFS找到的终点v一定是树的直径的一个端点证明:
1) 如果u 是直径上的点,则v显然是直径的终点(因为如果v不是的话,则必定存在另一个点w使得u到w的距离更长,则于BFS找到了v矛盾)
2) 如果u不是直径上的点,则u到v必然于树的直径相交(反证),那么交点到v 必然就是直径的后半段了所以v一定是直径的一个端点,所以从v进行BFS得到的一定是直径长度
Practice One:HDU 4607
题意:
给定你一棵树,每条边的长度为1,求要走k个点,,需要走的最短的长度。
分析:
求出树的直径D,如果k-1<=D那么答案就是k-1;如果k-1>D,那么答案就是(k-1) * 2 - m;
代码如下:
#include <iostream> #include <cstring> #include <algorithm> #include <cstdio> #include <queue> using namespace std; const int maxn = 200010; struct nod { int to,next,w; } edge[maxn]; int head[maxn],ip; int n,m; bool vis[maxn]; int dis[maxn]; void init() { ip=0; memset(head,-1,sizeof(head)); } void add(int u,int v,int w) { edge[ip].to=v; edge[ip].w=w; edge[ip].next=head[u]; head[u]=ip++; } void BFS(int u) { memset(vis,0,sizeof(vis)); memset(dis,0,sizeof(dis)); queue<int > Q; Q.push(u); vis[u]=1; while(!Q.empty()) { int top = Q.front(); Q.pop(); for(int i=head[top]; i!=-1; i=edge[i].next) { int v= edge[i].to; if(!vis[v]) { vis[v]=1; Q.push(v); dis[v]=dis[top]+edge[i].w; } } } } int TreeDiameter() { BFS(1); int u,Size=0; for(int i=1; i<=n; i++) { if(dis[i]>Size) Size=dis[i],u=i; } BFS(u); Size=0; for(int i=1; i<=n; i++) { if(dis[i]>Size) Size=dis[i]; } return Size; } int main() { int t; scanf("%d",&t); while(t--) { scanf("%d%d",&n,&m); init(); for(int i=0; i<n-1; i++) { int u,v; scanf("%d%d",&u,&v); add(u,v,1); add(v,u,1); } int D = TreeDiameter(); for(int i=0; i<m; i++) { int k; scanf("%d",&k); k--; if(k<=D) printf("%d\n",k); else printf("%d\n",2*k-D); } } return 0; }
Practice Two: HDU2196
题意:
求树上一点与离它最远的点的距离。
代码如下:
#include <iostream> #include <cstring> #include <cstdio> #include <queue> #include <algorithm> using namespace std; const int maxn = 10000*2+10; struct nod { int to,next,w; } edge[maxn]; int head[maxn],ip; int n; bool vis[maxn]; int dis1[maxn],dis2[maxn]; int d[maxn]; void init() { ip=0; memset(head,-1,sizeof(head)); } void add(int u,int v,int w) { edge[ip].to=v; edge[ip].w=w; edge[ip].next=head[u]; head[u]=ip++; } int get_point(int u) { memset(vis,0,sizeof(vis)); memset(d,0,sizeof(d)); queue <int >Q; Q.push(u); vis[u]=1; int mn = 0,st=u; while(!Q.empty()) { int top = Q.front(); Q.pop(); for(int i=head[top]; i!=-1; i=edge[i].next) { int v=edge[i].to; if(!vis[v]) { vis[v]=1; d[v]=edge[i].w+d[top]; if(d[v]>mn) mn=d[v],st=v; Q.push(v); } } } return st; } int main() { while(~scanf("%d",&n)) { init(); for(int i=2; i<=n; i++) { int u,w; scanf("%d%d",&u,&w); add(i,u,w); add(u,i,w); } // for(int i=1; i<=n; i++) { // for(int j=head[i]; j!=-1; j=edge[j].next) { // printf("(%d , %d) ",i,edge[j].to); // } // puts(""); // } int st = get_point(1); st = get_point(st); for(int i=1; i<=n; i++) dis1[i]=d[i]; get_point(st); for(int i=1; i<=n; i++) dis2[i]=d[i]; for(int i=1; i<=n; i++) { printf("%d\n",max(dis1[i],dis2[i])); } } return 0; }
版权声明:本文为博主原创文章,未经博主允许不得转载。
标签:
原文地址:http://blog.csdn.net/bigbigship/article/details/47252635