中石油训练赛 - Perfect Tree(dfs)
題目描述
Given a positive integer k, we define a rooted tree to be k-perfect, if and only if it meets both conditions below:
?Each node is either a leaf node or having exactly k direct offsprings.
?All leaf nodes have the same distance to the root (i.e., all leaf nodes are of the same depth).
Now you are given an unrooted tree, and you should answer these questions:
?Is it possible to assign it a root, so that the tree becomes k-perfect for some positive integer k?
?If possible, what is the minimal k?
?
?
輸入
Read from the standard input.
Each input contains multiple test cases.
The first line contains a single positive integer T, indicating the number of test cases.
For each test case, its first line contains a positive integer n, describing the number of tree nodes. Each of the next n???1 lines contains two space-separated integers u and v, which means there exists an edge between node u and v on the tree.
It is guaranteed each test case gives a valid unrooted tree, and the nodes are numbered with consecutive integers from 1 to n.
The sum of n in each input will not exceed 106.
?
?
輸出
Write to the standard output.
For each test case, output a single integer in a line:
?If the answer to the first question is "No", output ?1.
?Otherwise, output the minimal k.
?
?
樣例輸入
2 7 1 4 4 5 3 1 2 3 7 3 4 6 7 1 4 1 5 1 2 5 3 5 6 5 7樣例輸出
2 -1題目鏈接:點擊查看
題目大意:給出一棵樹,要求判斷是否滿足完全平衡k叉樹的要求,若滿足輸出k,不滿足輸出-1
完全k叉樹的要求:
題目分析:這個題目真的服了,好久沒做過這么惡心的題目了,不是題目惡心,是數據惡心,這些稍后再說,這個題目理解起來很簡單,用dfs或bfs實現一下再分類討論一下就ok了,要求每個節點有k個直接相連的子節點,我們可以通過鄰接表內儲存的點數來直接得出與k相連的節點個數,然后我們可以通過度數來判斷每個節點的種類,一般情況下,度數為k的話為根節點,度數為k+1的話為中間節點,度數為1的話就是葉節點了,特殊情況是n<=3時,答案都輸出1即可,因為三個點若想形成一棵樹那只能形成一條直線,如果要判斷葉子節點的深度,我們可以跑一邊dfs就行了,簡單dp的模板,不多贅述了
簡單的說一下,整個過程就是:讀邊+存邊(無向圖)->根據度數找出根節點->對根節點跑一邊dfs更新每個點的深度->判斷是否滿足條件
那么在說一下這個題的種種坑點吧,首先是cout卡時間,用cout時間能到2s,全部輸出改為printf后時間下降到0.8秒,達到題目給出的時間范圍內,關于cout卡時間這里就不多追究了,有個特殊點題目也沒給出,當n=1時,只有一個點的時候,答案肯定是0吧?不然你在題目中說一下也行吧?為什么答案會是1??1個點能形成完全1叉樹?真的服了,我們隊今下午調了兩個小時這個題,愣是被這個數據卡住,還有個很惡心人的地方就是,手寫鄰接表會爆內存,只有vector的鄰接表才能勉強在內存范圍內實現,大概原因是用手寫鄰接表得多開大概3個1e6的int數組吧,也是沒辦法了,之前見過卡vector時間的題目,第一次見卡手寫鄰接表內存的。。真的神仙題,給跪了,下午WA了9發人都自閉了,直接上代碼吧:
#include<iostream> #include<cstdio> #include<vector> using namespace std; vector<int>v[1010000];//鄰接表要用vector開,不然會被卡內存 int deep[1010000];//儲存每個節點的深度 void dfs(int u,int fa,int d) {deep[u]=d;for(int i=0;i<v[u].size();i++){int to=v[u][i];if(to==fa)continue;dfs(to,u,d+1);} } int main(void){int T,n,x,y;cin>>T;while(T--){scanf("%d",&n);for(int i=1;i<=n;i++)//注意初始化v[i].clear();for(int i=1;i<n;i++){//鄰接表的size()函數就是每個點的度數,這個題目用起來比較方便scanf("%d%d",&x,&y);v[x].push_back(y);v[y].push_back(x);}if(n<=3)//小于3時輸入完后直接輸出1即可{printf("1\n");continue;}int maxl=0;int fflag=0;for(int i=1;i<=n;i++){//找到最大的度數int len=v[i].size();if(len==n-1){printf("%d\n",n-1);fflag=1;break;}maxl=max(maxl,len);}if(fflag)continue;int k=maxl-1;//按照理論上的公式,根節點的度數為最大入度減一int root;bool flag=true;for(int i=1;i<=n;i++){//找到根節點if(v[i].size()==k){root=i;break;}if(i==n)flag=false;}dfs(root,-1,0);//更新每個點的深度int de=-1;for(int i=1;i<=n;i++)//分類討論每個節點的符合情況{if(i!=root){if(v[i].size()==1)//ye jie dian{if(de==-1)de=deep[i];else if(deep[i]!=de){flag=false;break;} }else{if(v[i].size()!=k+1){flag=false;break;}}}else{//cout<<root<<" "<<k<<" "<<v[root].size()<<"|\n";if(v[root].size()!=k){flag=false;break;}}}if(flag)//若都符合條件,輸出k,否則輸出-1printf("%d\n",k);elseprintf("-1\n");}return 0; }?
超強干貨來襲 云風專訪:近40年碼齡,通宵達旦的技術人生總結
以上是生活随笔為你收集整理的中石油训练赛 - Perfect Tree(dfs)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: HDU - 1160 FatMouse'
- 下一篇: HDU - 5015 233 Matri