1. 程式人生 > >hdu 4714 樹+DFS

hdu 4714 樹+DFS

題目連結:http://acm.hdu.edu.cn/showproblem.php?pid=4714

本來想直接求樹的直徑,再得出答案,後來發現是錯的。

思路:任選一個點進行DFS,對於一棵以點u為根節點的子樹來說,如果它的分支數大於1,那麼我們把這顆子樹從整棵樹上剪下來(優先減去),同時把這顆子樹的分支留下兩個,其它多餘的也剪掉,然後把剪下來的這些部分連線到根節點那裡,從而形成一條直鏈,總代價就是我們減的次數+把剪下來的部分連線到根節點+把最後的直鏈連成環。在這裡剪的次數=把剪下來的部分連線到根節點的次數,把最後的直鏈連成環只需要一步。

參考部落格:https://blog.csdn.net/cc_again/article/details/11407157

程式碼:

#include<iostream>
#include<cstring>
#include<algorithm>
#include<queue>
#include<map>
#include<stack>
#include<cmath>
#include<vector>
#include<set>
#include<cstdio>
#include<string>
#include<deque> 
using namespace std;
typedef 
long long LL; #define eps 1e-8 #define INF 0x3f3f3f3f #define maxn 1000005 int n,m,k,t,cnt; int ans; struct node{ int v,next; }edge[maxn*2]; int head[maxn]; void add(int u,int v){ edge[++cnt].v=v; edge[cnt].next=head[u]; head[u]=cnt; } int DFS(int u,int pre){ int num=0; for(int i=head[u];i!=-1
;i=edge[i].next){ int v=edge[i].v; if(v==pre) continue; num+=DFS(v,u); } if(num>1){//如果以點u為根節點的子樹的分支數大於1 if(u==1) ans+=num-2; else ans+=num-1; return 0;//這顆子樹剪斷了,所以返回0 } return 1;//分支數只有一個 } int main() { scanf("%d",&t); while(t--){ scanf("%d",&n); int u,v; cnt=0; memset(head,-1,sizeof(head)); for(int i=1;i<n;i++){ scanf("%d%d",&u,&v); add(u,v); add(v,u); } ans=0; DFS(1,-1); printf("%d\n",ans*2+1); } return 0; }