您的位置:首页 > 其它

【树形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

然后,就可分别把树根转移到其它结点时,每个点的最小孩子、最小子孙求出。

代码:

#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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: