zoukankan      html  css  js  c++  java
  • bzoj2599: [IOI2011]Race

    题目链接

    bzoj2599: [IOI2011]Race

    题解

    点分治,用t[k]表示子树中距离root为k 的最小边路径
    转移时先与前边子树和合并更新答案,然后更新距离父节点最优值,这样就保证不在同一子树内了
    每次分层的时候记得清除答案

    代码

    #include<cstdio> 
    #include<cstring> 
    #include<algorithm> 
    inline int read() { 
        int x = 0,f = 1; 
        char c = getchar(); 
        while(c < '0' || c > '9'){if(c == '-')f = -1;c = getchar(); } 
        while(c <= '9' && c >= '0')x = x * 10 + c - '0',c = getchar(); 
        return x * f; 
    } 
    #define INF 1000000007
    const int maxn = 200007;
    struct node {
        int v,w,next;
    } edge[maxn << 1]; 
    int head[maxn],num;
    inline void add_edge(int u,int v,int w) { 
        edge[++ num].v = v;edge[num].w = w;edge[num].next = head[u];head[u] = num;
    } 
    int n,k,root; 
    bool vis[maxn]; 
    int dis[maxn],son[maxn],f[maxn],deep[maxn],t[1000007],tot; 
    void get_root(int x,int fa) { 
        son[x] = 1;f[x] = 0; 
        for(int i = head[x];i;i = edge[i].next) { 
            int v = edge[i].v; 
            if(v == fa || vis[v]) continue;     
            get_root(v,x); 
            son[x] += son[v]; f[x] = std::max(f[x],son[v]); 
        } 
        f[x] = std::max(tot - son[x],f[x]); 
        if(f[x] < f[root])root = x; 
    } 
    int ans = INF; 
    void calc(int x,int fa) { 
        if(dis[x] <= k) ans = std::min(ans,deep[x] + t[k - dis[x]]); 
        else return;
        for(int i = head[x];i;i = edge[i].next) { 
            int v = edge[i].v; 
            if(vis[v] || edge[i].v == fa) continue; 
            deep[v] = deep[x] + 1; 
            dis[v] = dis[x] + edge[i].w; 
            calc(v,x); 
        }   
    } 
    void update(int x,int fa,bool ty) { 
        if(dis[x] <= k) { 
            if(ty)t[dis[x]] = std::min(t[dis[x]],deep[x]); 
            else t[dis[x]] = n; 
        } 
        for(int i = head[x];i;i = edge[i].next) { 
            int v = edge[i].v; 
            if(v != fa && !vis[v]) update(v,x,ty); 
        } 
    } 
    void sol(int x) { 
        vis[x] = 1; t[0] = 0; 
        for(int i = head[x];i;i = edge[i].next) { 
            int v = edge[i].v;
            if(vis[v]) continue; 
            deep[v] = 1;dis[v] = edge[i].w; 
            calc(v,0);update(v,0,1); 
        } 
        for(int i = head[x];i;i = edge[i].next) 
            if(!vis[edge[i].v]) update(edge[i].v,0,0);
        for(int i = head[x];i;i = edge[i].next) {  
                if(!vis[edge[i].v]) { 
                root = 0; 
                tot = son[edge[i].v]; 
                get_root(edge[i].v,0); sol(root); 
            }       
        } 
    } 
    int main() { 
        n = read(),k = read(); 
        for(int i = 1;i <= k;++ i) t[i] = n; 
        for(int u,v,w,i = 1;i < n;++ i) { 
            u = read() + 1,v = read() + 1,w = read(); 
            add_edge(u,v,w); add_edge(v,u,w); 
        }   
        ans = tot = n;f[0] = n; 
        get_root(1,0); 
        sol(root); 
        printf("%d
    ",ans == n ? -1 : ans); 
        return 0; 
    } 
    
    
  • 相关阅读:
    一、第一个小程序
    Golang学习笔记
    第四章 自上而下分析
    个人vim配置
    第三章 词法分析
    3.7 TCP拥塞控制
    3.6 拥塞控制原理
    3.5 面向连接的运输:TCP
    3.4可靠数据传输的原理
    3.3 无连接运输:UDP
  • 原文地址:https://www.cnblogs.com/sssy/p/9249348.html
Copyright © 2011-2022 走看看