题意:
给出一个n,代表一棵树有n个结点,接下去给出 n - 1 行,代表两个相连的结点
从小到大输出结点,结点满足的条件:当删去这个结点和与它相邻的边后,剩下的每一部分的节点都 ≤ n/2
思路:
用vector存邻边
从小到大输出结点 --->book标记最后再for循环遍历一遍即可
node数组存储的是该结点下所有的结点总和
看代码比较好理解
dfs部分代码:
int dfs(int x) { bool flag=0; node[x]=1; for(int i=0; i<v[x].size(); i++) { int p=v[x][i]; if(book1[p]==0) { book1[x]=1;//注意这边标记谁 int w=dfs(p);//用一个变量代替,不要去调用两次dfs,因为状态有所改变 if(w>n/2) flag=1; node[x]+=w; } } if(flag==0&&n-node[x]<=n/2) book2[x]=1; return node[x]; }
AC代码:
#include<stdio.h> #include<iostream> #include<string.h> #include<vector> using namespace std; const int N=10020; int n,node[N]; bool book1[N],book2[N]; vector<int>v[N]; int dfs(int x) { bool flag=0; node[x]=1; for(int i=0; i<v[x].size(); i++) { int p=v[x][i]; if(book1[p]==0) { book1[x]=1;//注意这边标记谁 int w=dfs(p);//用一个变量代替,不要去调用两次dfs,因为状态有所改变 if(w>n/2) flag=1; node[x]+=w; } } if(flag==0&&n-node[x]<=n/2) book2[x]=1; return node[x]; } int main() { while(cin>>n) { memset(book1,0,sizeof(book1)); memset(book2,0,sizeof(book2)); for(int i=1; i<n; i++) { int x,y; cin>>x>>y; v[x].push_back(y); v[y].push_back(x); } book1[1]=1; dfs(1); for(int i=1; i<=n; i++) { if(book2[i]) cout<<i<<endl; } } return 0; }
在网上看到这一片是用树形dp写的,下次学习,今天学不动了: