原题直通车: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; }