hdu-6228 Tree 2017年ICPC瀋陽站L題 DFS+思維
阿新 • • 發佈:2019-01-03
題目連結
題意
題目比較難理解,讀懂樣例就會好一點。大概就是給出一棵有N個結點的樹,有K種色彩對樹的結點進行染色,然後連線所有相同顏色的點,並將經過的邊組成一個邊集Ei,最後取所有邊集的交集的最大值。說白了就是連線所有顏色相同的點,看有幾個邊所有顏色的路線都經過。求這個的最大值。
題解
這個題最開始想的是,每個點可以是多個邊的結點,因為我們需要考慮某個邊是否能讓所有的集合都經過,換而言之,只有這個點有多個邊經過,那麼這個點對應的邊就是交集邊。所以計算每個結點經過邊的數量,大於1的全部整合起來再減1就是答案。當然這只是最簡單的思想,絕對是錯的。不過整體思路是沒問題的:即找到那些邊可以被經過多次。
為了使一個邊能被所有的顏色經過,最簡單思路:這個結點的所有子結點的數量>=K,這樣如果子結點最大可能是所有種類的顏色都從這個結點經過,那麼這個邊就是解集邊。
第一次這樣寫的時候WA了,後來才想到這樣我們可能將根或者比較高層的結點也算進去,因為是無向圖,所以我們應該考慮以一個結點為中心,分隔整個圖,要求左邊的結點和右邊的結點同時>=K,那麼這個結點最大可能下能經過至少K次,就是解集邊。
那麼就比較容易解決了,首先DFS統計所有結點的子結點數量。因為一定是樹,那麼隨便找個結點當做根就可以,統計的子結點數M就是一側的結點數量,另一側就是N-M。最後遍歷整個結點,滿足
資料的儲存方面,我是利用vector陣列,即利用鄰接表的方式儲存,滿足題目給出的要求。
C++ AC 程式碼 140ms
#include<iostream> #include<vector> #include<list> #include<string> #include<cmath> #include<algorithm> #include<map> #include<set> #include<utility> #include<queue> #include<sstream> #include<iterator> #include<math.h> #include<malloc.h> #include<string.h> #include<stack> #include<functional> #define TIME std::ios::sync_with_stdio(false) #define LL long long #define MOD 1000000007 #define MAX 201000 #define INF 0x3f3f3f3f using namespace std; int T,N,K; int number[MAX],step[MAX]; vector<int> maps[MAX]; int dfs(int root){ int len = maps[root].size(); if(len == 0) return 1; for(int i = 0;i < len;i++){ if(step[i] == 1) continue; step[i] = 1; number[root] += dfs(maps[root][i]); } return number[root]; } int main() { TIME; scanf("%d",&T); while(T--){ scanf("%d%d",&N,&K); memset(step,0,sizeof(step)); for(int i = 0;i <= N;i++){ maps[i].clear(); number[i] = 1; } int a,b; for(int i = 0;i < N-1;i++){ scanf("%d%d",&a,&b); maps[a].push_back(b); maps[b].push_back(a); } step[1] = 1; dfs(1); int ans = 0; for(int i = 1;i <= N;i++){ if(number[i] >= K && number[i] <= (N - K)){ ans++; } } printf("%d\n",ans); } system("pause"); return 0; }