16 36 42 55 41 55 33 1 2 31 53 3 1 4 Sample OutputCase #1:363HintFor the query {1,2, 3}:?node 4, 5, 6 are important nodes For the query {5}:?node 1,2, 3, 4, 6 are important nodes?node 5 is the lea of node 4 and node 3 For the query {3, 1,4}:? node 2, 5, 6 are important nodes
題意:樹中有n個(gè)點(diǎn),從1到n依次標(biāo)記,其中1為根。
樹中的點(diǎn)是否為一個(gè)satisfying的點(diǎn),需要滿足以下條件中的一個(gè):
1、該點(diǎn)是一個(gè)important的點(diǎn)
2、該點(diǎn)有多于2個(gè)important點(diǎn)的子孫
問有多少個(gè)satisfying的點(diǎn)。
思路:dfs跑一遍,統(tǒng)計(jì)好每個(gè)節(jié)點(diǎn)的父節(jié)點(diǎn)、孩子數(shù)以及深度,根據(jù)深度對unimportant的節(jié)點(diǎn)排序,從最深層的unimportant節(jié)點(diǎn)遍歷。具體看代碼吧,代碼有注釋,寫的很全了。
#include <iostream>#include <cstdio>#include <cstring>#include <vector>#include <algorithm>using namespace std;#define SIZE 100000+10int T;//測試數(shù)int Case;int n;//節(jié)點(diǎn)數(shù)int q;//詢問數(shù)int u,v;int un;vector<int> vertice[SIZE];//存放有關(guān)聯(lián)的點(diǎn)int father[SIZE];//存放其父節(jié)點(diǎn)int son[SIZE];//存放兒子節(jié)點(diǎn)的個(gè)數(shù)int deep[SIZE];//存放節(jié)點(diǎn)的深度int unver[SIZE];//存放unimportant節(jié)點(diǎn)int unson[SIZE];//存放unimportant節(jié)點(diǎn)的兒子數(shù)void dfs(int ver, int fver, int d){//ver:當(dāng)前節(jié)點(diǎn) fver:其父節(jié)點(diǎn) d:當(dāng)前深度 father[ver] = fver; deep[ver] = d; int temp = vertice[ver].size();//與ver節(jié)點(diǎn)有關(guān)的節(jié)點(diǎn)數(shù) if(ver == 1)//若節(jié)點(diǎn)為1,其沒有父節(jié)點(diǎn),兒子數(shù)即與其有關(guān)的節(jié)點(diǎn)的個(gè)數(shù); son[ver] = temp; else//否則減去父節(jié)點(diǎn) son[ver] = temp - 1; for(int i=0; i<temp; i++) { int ver_1 = vertice[ver][i]; if(ver_1 == fver) continue; dfs(ver_1, ver, d+1); }}bool cmp(int a, int b){ return deep[a] > deep[b];}void Initial(){ for(int i=0; i<=n; i++) vertice[i].clear();}int main(){ scanf("%d",&T); Case = 1; while(T--) { printf("Case #%d:/n",Case++); scanf("%d %d",&n,&q); Initial(); for(int i=1;i<n;i++) { cin>>u>>v; vertice[u].push_back(v); vertice[v].push_back(u); } dfs(1,0,0); for(int i=0;i<q;i++) { scanf("%d",&un); for(int j=0; j<un; j++) { scanf("%d",&unver[j]); unson[unver[j]]=son[unver[j]]; } sort(unver, unver+un, cmp);//按深度對節(jié)點(diǎn)排序 int num = n-un; for(int j=0; j<un; j++) {//節(jié)點(diǎn)是從最深處開始遍歷 //則一個(gè)節(jié)點(diǎn)的孩子一定都是important節(jié)點(diǎn) if(unson[unver[j]]>=2) num++; else if(unson[unver[j]] == 0) {//該節(jié)點(diǎn)為葉子節(jié)點(diǎn),那么父節(jié)點(diǎn)相當(dāng)于沒有這個(gè)孩子 unson[father[unver[j]]]--; } } printf("%d/n",num); } } return 0;}
新聞熱點(diǎn)
疑難解答