hdu 4607 Park Visit 求树的直径
生活随笔
收集整理的這篇文章主要介紹了
hdu 4607 Park Visit 求树的直径
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
題目鏈接:http://acm.hdu.edu.cn/showproblem.php?pid=4607
Claire and her little friend, ykwd, are travelling in Shevchenko's Park! The park is beautiful - but large, indeed. N feature spots in the park are connected by exactly (N-1) undirected paths, and Claire is too tired to visit all of them. After consideration, she decides to visit only K spots among them. She takes out a map of the park, and luckily, finds that there're entrances at each feature spot! Claire wants to choose an entrance, and find a way of visit to minimize the distance she has to walk. For convenience, we can assume the length of all paths are 1.Claire is too tired. Can you help her? 題意描述:小伙伴在公園里玩,公園里有N個景點,由n-1條無向路徑連通(每條路徑長度為1)。現(xiàn)在小伙伴想?yún)⒂^其中k個景點,并且要求所走的路徑最短。求最短路徑。 算法分析:首先知道這是一個無向連通圖,形如樹形結(jié)構(gòu)。假設公園里有一條很長的路徑,包含了比k大的景點個數(shù),這時我們要走完k個景點的最短路徑就是k-1(沿著這條路往下走即可),如果沒有k個呢,就要想著盡量少的景點在別的路徑(因為這條路徑上景點個數(shù)多,走到別的路徑還得回來繼續(xù)往下走)。由此,可以想到求樹的直徑就是了。(關于求解樹的直徑的證明網(wǎng)上也有很多) 求樹的直徑算法:樹的直徑是指樹的最長簡單路。 求法: 兩遍BFS :先任選一個起點BFS找到最長路的終點,再從終點進行BFS,則第二次BFS找到的最長路即為樹的直徑; 原理:設起點為u,第一次BFS找到的終點v一定是樹的直徑的一個端點 證明:1) 如果u 是直徑上的點,則v顯然是直徑的終點(因為如果v不是的話,則必定存在另一個點w使得u到w的距離更長,則于BFS找到了v矛盾) 2) 如果u不是直徑上的點,則u到v必然于樹的直徑相交(反證),那么交點到v 必然就是直徑的后半段了所以v一定是直徑的一個端點,所以從v進行BFS得到的一定是直徑長度 1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cstdlib> 5 #include<cmath> 6 #include<algorithm> 7 #include<queue> 8 #define inf 0x7fffffff 9 using namespace std; 10 const int maxn=100000+10; 11 const int M = 100000+10; 12 13 int n,m; 14 struct node 15 { 16 int v,w; 17 int next; 18 }edge[M*3]; 19 int head[maxn],edgenum; 20 21 void add(int u,int v,int w) 22 { 23 edge[edgenum].v=v ;edge[edgenum].w=w ; 24 edge[edgenum].next=head[u] ;head[u]=edgenum++ ; 25 26 edge[edgenum].v=u ;edge[edgenum].w=w ; 27 edge[edgenum].next=head[v] ;head[v]=edgenum++ ; 28 } 29 30 int vis[maxn],d[maxn]; 31 int bfs(int from) 32 { 33 queue<int> Q; 34 Q.push(from); 35 memset(d,-1,sizeof(d)); 36 memset(vis,0,sizeof(vis)); 37 d[from]=1; 38 vis[from]=1; 39 int maxlen=-1,k=0; 40 while (!Q.empty()) 41 { 42 int u=Q.front() ;Q.pop() ; 43 for (int i=head[u] ;i!=-1 ;i=edge[i].next) 44 { 45 int v=edge[i].v; 46 if (!vis[v]) 47 { 48 vis[v]=1; 49 d[v]=d[u]+1; 50 if (d[v]>maxlen) 51 { 52 maxlen=d[v]; 53 k=v; 54 } 55 Q.push(v); 56 } 57 } 58 } 59 return k; 60 } 61 62 int main() 63 { 64 int t; 65 scanf("%d",&t); 66 while (t--) 67 { 68 memset(head,-1,sizeof(head)); 69 edgenum=0; 70 int a,b; 71 scanf("%d%d",&n,&m); 72 for (int i=1 ;i<=n-1 ;i++) 73 { 74 scanf("%d%d",&a,&b); 75 add(a,b,1); 76 } 77 int v=bfs(1); 78 int u=bfs(v); 79 int maxlen=d[u]; 80 //cout<<"debug= "<<maxlen<<endl; 81 for (int i=0 ;i<m ;i++) 82 { 83 scanf("%d",&a); 84 if (a<=maxlen) printf("%d\n",a-1); 85 else printf("%d\n",maxlen-1+(a-maxlen)*2); 86 } 87 } 88 return 0; 89 }
?
轉(zhuǎn)載于:https://www.cnblogs.com/huangxf/p/4366979.html
《新程序員》:云原生和全面數(shù)字化實踐50位技術專家共同創(chuàng)作,文字、視頻、音頻交互閱讀總結(jié)
以上是生活随笔為你收集整理的hdu 4607 Park Visit 求树的直径的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 小牛电动ipo定价9美元 计划募集资金6
- 下一篇: 找最大子矩阵