HDU - 4008 Parent and son

题意:

给定一棵有 n n 个结点的树,再有 q q 次询问,每次询问以 X X 为根时, Y Y 的子结点中、后代结点中编号最小的结点各是哪个,若 Y Y 是叶结点,输出无解。 ( n , q 1 0 5 ) (n,q \leq 10^5)

链接:

https://vjudge.net/problem/HDU-4008

解题思路:

如果仅要求以 1 1 为根,则树形 d p dp 一下就可以得到答案。考虑换根,共两种情况,①: X X Y Y 的祖先,则 Y Y 会多一棵往父结点方向的子树;②:否则直接查询,答案不变。

参考代码:

#include<bits/stdc++.h>

using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
#define sz(a) ((int)a.size())
#define pb push_back
#define lson (rt << 1)
#define rson (rt << 1 | 1)
#define gmid (l + r >> 1)
const int maxn = 1e5 + 5;
const int inf = 0x3f3f3f3f;
const int mod = 1e9 + 7;

vector<pii> qr[maxn];
vector<int> G[maxn];
int vis[maxn], mn[maxn][2], mn2[maxn][2], fmn[maxn][2], pmn[maxn][2];
pii ans[maxn];
int n, q;

void dfs1(int u, int f){

    mn[u][0] = mn[u][1] = inf;
    mn2[u][0] = mn2[u][1] = inf;
    pmn[u][0] = pmn[u][1] = 0;
    for(auto &v : G[u]){
    
        if(v == f) continue;
        dfs1(v, u);
        if(v < mn[u][0]){

            mn2[u][0] = mn[u][0];
            mn[u][0] = v, pmn[u][0] = v;
        }
        else if(v < mn2[u][0]){

            mn2[u][0] = v;
        }
        int w = min(v, mn[v][1]);
        if(w < mn[u][1]){

            mn2[u][1] = mn[u][1];
            mn[u][1] = w, pmn[u][1] = v;
        }
        else if(w < mn2[u][1]){

            mn2[u][1] = w;
        }
    }
}

void dfs2(int u, int f){

    vis[u] = 1;
    for(auto &it : qr[u]){

        int v = it.second, p = it.first;
        if(vis[v]){

            if(vis[pmn[v][0]]){

                ans[p].first = min(fmn[v][0], mn2[v][0]);
            }
            else{

                ans[p].first = min(fmn[v][0], mn[v][0]);
            }
            if(vis[pmn[v][1]]){

                ans[p].second = min(fmn[v][1], mn2[v][1]);
            }
            else{

                ans[p].second = min(fmn[v][1], mn[v][1]);
            }
        }
        else{

            ans[p] = {mn[v][0], mn[v][1]};
        }
    }
    for(auto &v : G[u]){

        if(v == f) continue;
        fmn[v][0] = u;
        if(v == pmn[u][1]){

            fmn[v][1] = min(min(u, fmn[u][1]), mn2[u][1]);
        }
        else{

            fmn[v][1] = min(min(u, fmn[u][1]), mn[u][1]);
        }
        dfs2(v, u);
    }
    vis[u] = 0;
}

int main(){

    ios::sync_with_stdio(0); cin.tie(0);
    int t; cin >> t;
    while(t--){

        cin >> n >> q;
        for(int i = 1; i <= n; ++i){

            G[i].clear();
            qr[i].clear();
        }
        for(int i = 1; i < n; ++i){

            int u, v; cin >> u >> v;
            G[u].pb(v), G[v].pb(u);
        }
        for(int i = 1; i <= q; ++i){

            int x, y; cin >> x >> y;
            qr[x].pb({i, y});
        }
        dfs1(1, 0);
        fmn[1][0] = fmn[1][1] = inf;
        dfs2(1, 0);
        // for(int i = 1; i <= n; ++i){

        //     cout << i << " : " << mn[i][0] << " " << mn2[i][0] << " "<< fmn[i][0] << " | "
        //     << mn[i][1] << " " << mn2[i][1] << " " << fmn[i][1] << endl;
        // }
        for(int i = 1; i <= q; ++i){

            if(ans[i].first == inf) cout << "no answers!\n";
            else cout << ans[i].first << " " << ans[i].second << "\n";
        }
        cout << "\n";
    }
    return 0;
}
发布了55 篇原创文章 · 获赞 0 · 访问量 1244

猜你喜欢

转载自blog.csdn.net/weixin_44059127/article/details/104082599
SON
今日推荐