【树形DP】 HDU 4916 Count on the path

通道

题意:一棵树,求不经过路径的最小标号

代码:

#include <iostream>
#include <cstring>
#include <string>
#include <vector>
#include <cstdio>
#include <cmath>
#include <algorithm>
using namespace std;
 
#define maxn 1005000
#define inf 0x3f3f3f3f
 
int child[maxn][4];
int subtree[maxn];
int path[maxn];
int fa[maxn];
int bel[maxn];
int que[maxn];
int qh, qt;
int n, nQ;
 
int head[maxn];
int nxt[maxn<<1];
int vv[maxn<<1];
int tot;
 
void add_Edge(int u,int v)
{
    vv[tot] = v; nxt[tot] = head[u]; head[u] = tot++;
}
 
 
void bfs()
{
    qh = qt = 0;
    que[qt++] = 1; fa[1] = -1;
    while (qh < qt){
        int u = que[qh++];
        for (int i = head[u]; ~i; i=nxt[i]){
            int v = vv[i];
            if (v == fa[u]) continue;
            fa[v] = u;
            que[qt++] = v;
        }
    }
    for (int i = 0; i <= n; ++i){
        for (int j = 0; j < 4; ++j){
            child[i][j] = inf;
        }
    }
    for (int i = n - 1; i >= 0; --i){
        int u = que[i]; subtree[u] = u;
        for (int j = head[u]; ~j; j=nxt[j]){
            int v = vv[j];
            if (v == fa[u]) continue;
            child[u][3] = subtree[v];
            sort(child[u], child[u] + 4);
        }
        subtree[u] = min(subtree[u], child[u][0]);
    }
 
    qh = qt = 0;
    for (int i = head[1]; ~i; i=nxt[i]){
        int v = vv[i];
        que[qt++] = v;
        bel[v] = subtree[v];
        path[v] = inf;
    }
    while (qh < qt){
        int u = que[qh++];
        for (int i = head[u]; ~i; i=nxt[i]){
            int v = vv[i];
            if (v == fa[u]) continue;
            bel[v] = bel[u];
            if (subtree[v] == child[u][0]){
                path[v] = min(path[u], child[u][1]);
            }
            else{
                path[v] = min(path[u], child[u][0]);
            }
            que[qt++] = v;
        }
        path[u] = min(path[u], child[u][0]);
    }
}
 
 
int query(int qu, int qv){
    if (qu > qv) swap(qu, qv);
    if (qu != 1 && bel[qu] == bel[qv]) return 1;
    int i = 0;
    while (child[1][i] == bel[qu] || child[1][i] == bel[qv]){
        i++;
    }
    int ret = qu == 1 ? path[qv] : min(path[qu], path[qv]);
    ret = min(ret, child[1][i]);
    return ret;
}
 
inline void scan(int &n)
{
    char cc;
    for (; cc = getchar(), cc<'0' || cc>'9';);
    n = cc - '0';
    for (; cc = getchar(), cc >= '0'&&cc <= '9';)
        n = n * 10 + cc - '0';
}
 
int main()
{
    while (cin >> n >> nQ){
        tot = 0; memset(head, -1, sizeof(head));
        int ui, vi;
        for (int i = 0; i < n - 1; ++i){
            //scan(ui); scan(vi);
            scanf("%d%d", &ui, &vi);
            add_Edge(ui, vi);
            add_Edge(vi, ui);
        }
        bfs();
        int last = 0;
        for (int i = 0; i < nQ; ++i){
            //scan(ui); scan(vi);
            scanf("%d%d", &ui, &vi);
            ui ^= last; vi ^= last;
            printf("%d\n", last=query(ui, vi));
        }
    }
    return 0;
}
View Code

 

posted @ 2015-08-09 13:38  mithrilhan  阅读(260)  评论(0编辑  收藏  举报