【树形DP】 HDU 4008 Parent and son
2014-01-15 16:55
288 查看
原题直通车:HDU 4008 Parent and son
分析:
如果a、b之间存在一条边,那么把a当树根和把b当树根只在a, b这两结点的信息有所区别,其它的不变。
所以,先以任意一个点做为根的所求出每个点的最小孩子min_son、最小子孙min_des
然后,就可分别把树根转移到其它结点时,每个点的最小孩子、最小子孙求出。
代码:
分析:
如果a、b之间存在一条边,那么把a当树根和把b当树根只在a, b这两结点的信息有所区别,其它的不变。
所以,先以任意一个点做为根的所求出每个点的最小孩子min_son、最小子孙min_des
然后,就可分别把树根转移到其它结点时,每个点的最小孩子、最小子孙求出。
代码:
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<vector> using namespace std; const int maxn=100005; vector<int>G[maxn]; vector< pair<int,int> >Q[maxn]; int min_son[maxn], min_des[maxn]; int ans1[maxn], ans2[maxn]; bool vis[maxn]; void dfs(int cnt) { min_son[cnt]=maxn, min_des[cnt]=maxn; vis[cnt]=true; int len=G[cnt].size(); for(int i=0; i<len; ++i) { int son=G[cnt][i]; if(!vis[son]) { dfs(son); min_son[cnt]=min(min_son[cnt], son); min_des[cnt]=min(min_des[cnt], min_des[son]); } } min_des[cnt]=min(min_des[cnt], min_son[cnt]); } int Min_son(int cnt, int exp) { //除exp外 int len=G[cnt].size(), ret=maxn; for(int i=0; i<len; ++i) if(G[cnt][i]!=exp) ret=min(ret, G[cnt][i]); return ret; } int Min_des(int cnt, int exp) { //除exp外 int len=G[cnt].size(), ret=maxn; for(int i=0; i<len; ++i) if(G[cnt][i]!=exp) ret=min(ret, min(G[cnt][i],min_des[G[cnt][i]])); return ret; } void dfs_ans(int cnt) { //cout<<cnt<<endl; vis[cnt]=true; int len=Q[cnt].size(); for(int i=0; i<len; ++i) { int y=Q[cnt][i].first, k=Q[cnt][i].second; ans1[k]=min_son[y], ans2[k]=min_des[y]; } len=G[cnt].size(); for(int i=0; i<len; ++i) { int son=G[cnt][i]; if(!vis[son]) { int cnt_min_son=min_son[cnt], son_min_son=min_son[son]; int cnt_min_des=min_des[cnt], son_min_des=min_des[son]; if(son==min_son[cnt]) min_son[cnt]=Min_son(cnt, son); min_son[son]=min(min_son[son], cnt); if(son==min_des[cnt]||min_des[son]==min_des[cnt]) min_des[cnt]=Min_des(cnt, son); min_des[son]=min(min_des[son], min(min_des[cnt],cnt)); dfs_ans(son); min_son[cnt]=cnt_min_son, min_son[son]=son_min_son; min_des[cnt]=cnt_min_des, min_des[son]=son_min_des; } } } int main() { int T; scanf("%d",&T); while(T--) { int n, m; scanf("%d%d",&n,&m); for(int i=0; i<n; ++i){ G[i].clear(), Q[i].clear(); vis[i]=false; } for(int i=1; i<n; ++i) { int a, b; scanf("%d%d",&a, &b); --a, --b; G[a].push_back(b); G[b].push_back(a); } dfs(0); for(int i=0; i<m; ++i) { int x, y; scanf("%d%d",&x,&y); --x, --y; Q[x].push_back(make_pair(y, i)); } memset(vis, false, sizeof(vis)); dfs_ans(0); for(int i=0; i<m; ++i) { if(ans1[i]==maxn) puts("no answers!"); else { printf("%d %d\n", ++ans1[i], ++ans2[i]); } } puts(""); } return 0; }
相关文章推荐
- PVRTC compression
- 基于OPenStack平台的C++ API 设计
- 让程序只运行一个实例的四种方法
- Ajax之工厂模式封装XMLHttpRequest
- PreparedStatement的用法
- mysql建表常用sql语句分享
- 开源中国 Maven 库使用帮助
- 【LeetCode】N-Queens && 【九度】题目1140:八皇后
- 玩android 遇到的问题-2014年1月15日
- 拆掉你思维里的墙
- 从devstack开始 学习openstack
- 使用 Mcafee 镜像任务 建立升级服务器
- java 八字计算
- -1
- 单纯gdb调试android的so断点
- Java冒泡排序
- Android.mk中的变量的使用介绍(二)
- 英语学习方法
- CGContextAddArcToPoint看图说话
- santoku的安装问题