zoukankan      html  css  js  c++  java
  • 【HDU】HDU5664 Lady CA and the graph

    原题链接

    题解

    距离省选只有一周了我居然才开始数据结构康复计划

    这题很简单,就是点分树,然后二分一个值,我们计算有多少条路径大于这个值
    对于一个点分树上的重心,我们可以通过双指针的方法求出它子树里的路径任意搭配大于这个值的方案
    然后同一个子树里重复计算的删掉
    再计算和自己祖先之间的路径

    代码

    #include <bits/stdc++.h>
    #define fi first
    #define se second
    #define pii pair<int,int>
    #define mp make_pair
    #define pb push_back
    #define space putchar(' ')
    #define enter putchar('
    ')
    #define eps 1e-10
    #define MAXN 50005
    //#define ivorysi
    using namespace std;
    typedef long long int64;
    typedef unsigned int u32;
    typedef double db;
    template<class T>
    void read(T &res) {
        res = 0;T f = 1;char c = getchar();
        while(c < '0' || c > '9') {
    	if(c == '-') f = -1;
    	c = getchar();
        }
        while(c >= '0' && c <= '9') {
    	res = res * 10 +c - '0';
    	c = getchar();
        }
        res *= f;
    }
    template<class T>
    void out(T x) {
        if(x < 0) {x = -x;putchar('-');}
        if(x >= 10) {
    	out(x / 10);
        }
        putchar('0' + x % 10);
    }
    struct node {
        int to,next,val;
    }E[MAXN * 2];
    
    int N,sumE,head[MAXN],rt;
    int64 K;
    
    int dep[MAXN],fa[MAXN][20],d[MAXN],zz[MAXN];
    
    bool vis[MAXN];
    
    vector<int> poi;
    vector<int> dis[2][MAXN];
    int tot;
    void add(int u,int v,int c) {
        E[++sumE].to = v;
        E[sumE].next = head[u];
        E[sumE].val = c;
        head[u] = sumE;
    }
    void dfs(int u) {
        zz[u] = zz[fa[u][0]] + 1;
        for(int i = 1 ; i <= 18 ; ++i) fa[u][i] = fa[fa[u][i - 1]][i - 1];
        for(int i = head[u] ; i ; i = E[i].next) {
    	int v = E[i].to;
    	if(v != fa[u][0]) {
    	    fa[v][0] = u;
    	    dep[v] = dep[u] + E[i].val;
    	    dfs(v);
    	}
        }
    }
    int que[MAXN],ql,qr;
    int Calc_G(int st) {
        static int f[MAXN],siz[MAXN],son[MAXN];
        ql = 1;qr = 0;
        que[++qr] = st;f[st] = 0;siz[st] = 1;son[st] = 0;
        while(ql <= qr) {
    	int u = que[ql++];
    	for(int i = head[u] ; i ; i = E[i].next) {
    	    int v = E[i].to;
    	    if(v != f[u] && !vis[v]) {
    		siz[v] = 1;son[v] = 0;
    		f[v] = u;que[++qr] = v;
    	    }
    	}
        }
        int res = que[qr];
        for(int i = qr ; i >= 1 ; --i) {
    	int u = que[i];
    	if(f[u]) {
    	    siz[f[u]] += siz[u];
    	    son[f[u]] = max(son[f[u]],siz[u]);
    	}
    	son[u] = max(son[u],qr - siz[u]);
    	if(son[u] < son[res]) res = u;
        }
        return res;
    }
    void dfs_for_dis(int u,int f) {
        poi.pb(u);
        for(int i = head[u] ; i ; i = E[i].next) {
    	int v = E[i].to;
    	if(v != f && !vis[v]) {
    	    d[v] = d[u] + E[i].val;
    	    dfs_for_dis(v,u);
    	}
        }
    }
    
    void dfs_divide(int u) {
        int G = Calc_G(u);
        vis[G] = 1;
        for(int i = head[G] ; i ; i = E[i].next) {
    	int v = E[i].to;
    	if(!vis[v]) {
    	    poi.clear();
    	    d[v] = E[i].val;
    	    dfs_for_dis(v,G);
    	    ++tot;
    	    for(int j = 0 ; j < poi.size() ; ++j) {
    		dis[1][tot].pb(d[poi[j]]);
    		dis[0][G].pb(d[poi[j]]);
    	    }
    	}
        }
        for(int i = head[G] ; i ; i = E[i].next) {
    	int v = E[i].to;
    	if(!vis[v]) dfs_divide(v);
        }
    }
    int64 check(int mid) {
        int64 res = 0;
        for(int i = 1 ; i <= N ; ++i) {
    	int l = 0,r = dis[0][i].size() - 1;
    	while(r >= 0) {
    	    while(l < dis[0][i].size() && dis[0][i][r] + dis[0][i][l] < mid) ++l;
    	    if(dis[0][i][r] >= mid) res += 2;
    	    res += dis[0][i].size() - l;
    	    --r;
    	}
    	l = 0,r = dis[1][i].size() - 1;
    	while(r >= 0) {
    	    while(l < dis[1][i].size() && dis[1][i][r] + dis[1][i][l] < mid) ++l;
    	    res -= dis[1][i].size() - l;
    	    --r;
    	}
        }
        res /= 2;
        for(int i = 1 ; i <= N ; ++i) {
    	int t = dep[i] - mid;
    	int u = i;
    	for(int j = 18 ; j >= 0 ; --j) {
    	    if(fa[u][j] && dep[fa[u][j]] > t) {
    		u = fa[u][j];
    	    }
    	}
    	res -= zz[u] - zz[rt];
        }
        return res;
    }
    void Init() {
        read(N);read(rt);read(K);
        memset(head,0,sizeof(head));
        memset(vis,0,sizeof(vis));
        sumE = 0;tot = 0;
        for(int i = 1 ; i <= N ; ++i) {dis[0][i].clear();dis[1][i].clear();}
        
        int u,v,c;
        for(int i = 1 ; i < N ; ++i) {
    	read(u);read(v);read(c);
    	add(u,v,c);add(v,u,c);
        }
        dep[rt] = 0;
        fa[rt][0] = 0;
        dfs(rt);
        dfs_divide(rt);
        for(int i = 1 ; i <= N ; ++i) {
    	sort(dis[0][i].begin(),dis[0][i].end());
    	sort(dis[1][i].begin(),dis[1][i].end());
        }
    }
    void Solve() {
        Init();
        int L = 0,R = 500000001;
        while(L < R) {
    	int mid = (L + R + 1) >> 1;
    	if(check(mid) >= K) L = mid;
    	else R = mid - 1;
        }
        if(R == 0) {puts("NO");return;}
        out(L);enter;
    }
    int main() {
    #ifdef ivorysi
        freopen("f1.in","r",stdin);
    #endif
        int T;
        read(T);
        while(T--) Solve();
    }
    
  • 相关阅读:
    人生小悟1
    对偶传播神经网络(CPN)
    对偶传播神经网络(CPN)
    学习向量量化神经网络
    学习向量量化神经网络
    自组织特征映射神经网络(SOFM)
    自组织特征映射神经网络(SOFM)
    竞争学习的基本概念和原理
    竞争学习的基本概念和原理
    人工神经网络基础概念、原理知识(补)
  • 原文地址:https://www.cnblogs.com/ivorysi/p/10638749.html
Copyright © 2011-2022 走看看