zoukankan      html  css  js  c++  java
  • POJ 3728 tarjan+DP

    从这个好题我终于去学了学Tarjan, 因为发现ST毫无意义, 除了预处理, 其他还是要借鉴Tarjan;
    Tarjan其实很简单, 其实就是对于询问也开一个邻接表, 两个点的LCA就是:
    如果在访问u的时候发现v已经访问过了, 那么LCA就是find(u)
    至于这个题up, down, max, min的作用就不说了, 网上的主流代码
    是个好题, 初学Tarjan一定要去搞

    #include <vector>
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    
    #define N 400010
    #define next Next
    #define begin Begin
    #define pb push_back
    #define mem(a, b) memset(a, b, sizeof(a))
    #define rep(i, s, t) for(int i = s, end = t; i <= end; ++i)
    #define erep(i, u) for(int i = begin[u]; i != -1; i = next[i])
    
    bool vis[N];
    int to[N], next[N], begin[N], n, m, q;
    int e, res[N], w[N];
    int mx[N], mn[N], up[N], down[N], fa[N];
    vector<int> query[N], s[N];
    
    void add(int u, int v) {
        to[++e] = v;
        next[e] = begin[u];
        begin[u] = e;
    }
    
    int find(int x) {
        if(x == fa[x]) return x;
        int y = fa[x];
        fa[x] = find(fa[x]);
    
        up[x] = max(mx[y] - mn[x], max(up[x], up[y]));
        down[x] = max(mx[x] - mn[y], max(down[x], down[y]));
        mx[x] = max(mx[x], mx[y]);
        mn[x] = min(mn[x], mn[y]);
    
        return fa[x];
    }
    
    void LCA(int u) {
        int v;
        vis[u] = 1;
        for(int i = 0; i < (int) query[u].size(); i += 2)
            if(vis[v = query[u][i]]) {
                int f = find(v), id = query[u][i+1];
                if(id > 0) s[f].pb(u), s[f].pb(v);
                else s[f].pb(v), s[f].pb(u);
                s[f].pb(id > 0? id : -id);
            }
        erep(i, u) 
            if(!vis[v = to[i]]){
                LCA(v);
                fa[v] = u;
            }
        for(int i = 0; i < (int)s[u].size(); i += 3) {
            int x = s[u][i], y = s[u][i+1], id = s[u][i+2];
            find(x); find(y);
            res[id] = max(up[x], max(down[y], mx[y] - mn[x]));
        }
    }
    
    void init() {
        e = 0;
        mem(up, 0); mem(down, 0);
        mem(vis, 0);
        mem(begin, -1);
        rep(i, 0, n) fa[i] = i, s[i].clear(), query[i].clear();
    }
    
    int main() {
    #ifndef ONLINE_JUDGE
        freopen("data.in", "r", stdin);
        freopen("result.out", "w", stdout);
    #endif
        scanf("%d", &n);
        init();
        rep(i, 1, n) {
            scanf("%d", &w[i]);
            mx[i] = w[i];
            mn[i] = w[i]; 
        }
        rep(i, 1, n-1) {
            int u, v;
            scanf("%d%d", &u, &v);
            add(u, v); add(v, u);
        }
        scanf("%d", &m);
        rep(i, 1, m) {
            int u, v;
            scanf("%d%d", &u, &v);
            query[u].pb(v);
            query[u].pb(i);
            query[v].pb(u);
            query[v].pb(-i);
        }
    
        LCA(1);
        rep(i, 1, m) printf("%d
    ", res[i]);
        /*puts("%----------------%");
        rep(i, 1, n) 
            printf("%d %d %d %d
    ", up[i], down[i], mx[i], mn[i]);
            */
        return 0;
    }

    VECTOR巨慢。。。。

  • 相关阅读:
    利用Vista新技术WCF开发构建服务系统
    WCF开发入门的六个步骤
    C#开发WPF/Silverlight动画及游戏系列教程(Game Course):(一)让物体动起来①
    silverlight
    初探C#3.0
    通过托管代码和 Windows Vista 智能卡 API 来保护您的数据
    用例图
    类图
    Win7下MSN显示两个窗口问题
    设计模式初探
  • 原文地址:https://www.cnblogs.com/pbvrvnq/p/8530167.html
Copyright © 2011-2022 走看看