[ZJOI 2007] 捉迷藏

[题目链接]

       https://www.lydsy.com/JudgeOnline/problem.php?id=1095

[算法]

        首先建出点分树,然后每一个点开两个堆。“第一个堆记录子树中所有节点到父亲节点的距离 ,第二个堆记录所有子节点的堆顶 ,那么一个节点的堆2中的最大和次大加起来就是子树中经过这个节点的最长链。然后我们最后开一个全局的堆,记录所有堆2中最大值和次大值之和。那么全局的堆顶就是答   

        案

        时间复杂度 : O(NlogN ^ 2)

[代码]

        

#include<bits/stdc++.h>
using namespace std;
#define N 100010
#define M 500010
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;

int n , root , tot , timer;
int size[N] , head[N] , weight[N] , father[N] , ans[N];
bool visited[N] , light[N];
map< int , pair<int , int> > mp[N];

struct edge
{
        int to , nxt;
} e[M << 1];

struct Heap
{
        priority_queue< int > hp , era;
        inline void ins(int value)
        {
                hp.push(value);
        }
        inline void del(int value)
        {
                if (value != 0) era.push(value);
        }
        inline int max()
        {
                while (!hp.empty() && !era.empty() && era.top() == hp.top())
                {
                        hp.pop();
                        era.pop();
                }
                if (hp.empty()) return 0;
                else return hp.top();
        }
        inline int secmax()
        {
                int tmp = max();
                del(tmp);
                int ret = max();
                ins(tmp);
                return ret;
        }
} A , B[N] , C[N << 1];

template <typename T> inline void chkmax(T &x,T y) { x = max(x,y); }
template <typename T> inline void chkmin(T &x,T y) { x = min(x,y); }
template <typename T> inline void read(T &x)
{
    T f = 1; x = 0;
    char c = getchar();
    for (; !isdigit(c); c = getchar()) if (c == '-') f = -f;
    for (; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + c - '0';
    x *= f;
}
inline void addedge(int u , int v)
{
        ++tot;
        e[tot] = (edge){v , head[u]};
        head[u] = tot;
}
inline void getroot(int u , int father , int total)
{
        size[u] = 1;
        weight[u] = 0;
        for (int i = head[u]; i; i = e[i].nxt)
        {
                int v = e[i].to;
                if (v == father || visited[v]) continue;
                getroot(v , u , total);
                size[u] += size[v];
                chkmax(weight[u] , size[v]);
        }
        chkmax(weight[u] , total - size[u]);
        if (weight[u] < weight[root]) root = u;        
}
inline void dfs(int u , int father , int rt , int belong , int depth)
{
        mp[rt][u] = make_pair(belong , depth);
        C[belong].ins(depth);
        for (int i = head[u]; i; i = e[i].nxt)
        {
                int v = e[i].to;
                if (v == father || visited[v]) continue;
                dfs(v , u , rt , belong , depth + 1);
        }
}
inline void work(int u)
{
        visited[u] = true;
        for (int i = head[u]; i; i = e[i].nxt)
        {
                int v = e[i].to;
                if (!visited[v]) 
                {
                        dfs(v , u , u , ++timer , 1);
                        B[u].ins(C[timer].max());
                }
        }        
        ans[u] = B[u].max() + B[u].secmax();
        A.ins(ans[u]);
        for (int i = head[u]; i; i = e[i].nxt)
        {
                int v = e[i].to;
                if (!visited[v])
                {
                        root = 0;
                        getroot(v , u , size[v]);
                        father[root] = u;
                        work(root);
                }
        }
}

int main()
{
        
        read(n);
        for (int i = 1; i < n; i++)
        {
                int x , y;
                read(x); read(y);
                addedge(x , y);
                addedge(y , x);
        }
        int q;
        read(q);
        root = 0;
        weight[0] = n;
        getroot(1 , 0 , n);
        work(root);
        int cnt = n;
        while (q--)
        {
                char type[5];
                scanf("%s" , type);
                if (type[0] == 'C')
                {
                        int x , y;
                        scanf("%d" , &x);
                        y = x;
                        if (light[x])
                        {
                                light[x] = false;
                                ++cnt;
                                A.del(ans[x]);
                                ans[x] = B[x].max() + B[x].secmax();
                                A.ins(ans[x]);
                                x = father[x];
                                while (x != 0)
                                {
                                        pair<int , int> tmp = mp[x][y];
                                        B[x].del(C[tmp.first].max());
                                        C[tmp.first].ins(tmp.second);
                                        B[x].ins(C[tmp.first].max());
                                        A.del(ans[x]);
                                        if (light[x])
                                        {
                                                if (B[x].secmax()) ans[x] = B[x].max() + B[x].secmax();
                                                else ans[x] = 0;
                                        } else ans[x] = B[x].max() + B[x].secmax();
                                        A.ins(ans[x]);
                                        x = father[x];
                                }
                        } else
                        {
                                light[x] = true;
                                --cnt;
                                A.del(ans[x]);
                                if (B[x].secmax()) ans[x] = B[x].max() + B[x].secmax();
                                else ans[x] = 0;
                                A.ins(ans[x]);
                                x = father[x];
                                while (x != 0)
                                {
                                        pair<int , int> tmp = mp[x][y];
                                        B[x].del(C[tmp.first].max());
                                        C[tmp.first].del(tmp.second);
                                        B[x].ins(C[tmp.first].max());
                                        A.del(ans[x]);
                                        if (light[x])
                                        {
                                                if (B[x].secmax()) ans[x] = B[x].max() + B[x].secmax();
                                                else ans[x] = 0;
                                        } else ans[x] = B[x].max() + B[x].secmax();
                                        A.ins(ans[x]);
                                        x = father[x];
                                }
                        }
                 } else
                 {
                         if (!cnt) printf("-1
");
                        else if (cnt == 1) printf("0
");
                        else printf("%d
" , A.max());        
                }
        }
        return 0;
    
}
原文地址:https://www.cnblogs.com/evenbao/p/10540119.html