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

    链接:https://www.luogu.org/problemnew/show/P4149

    题目描述

    给一棵树,每条边有权。求一条简单路径,权值和等于 KK ,且边的数量最小。

    输入输出格式

    输入格式:

    第一行:两个整数 n,kn,k 。

    第二至 nn 行:每行三个整数,表示一条无向边的两端和权值 (注意点的编号从 00 开始)。

    输出格式:

    一个整数,表示最小边数量。

    如果不存在这样的路径,输出 -11 。

    输入输出样例

    输入样例#1: 复制
    4 3
    0 1 1
    1 2 2
    1 3 4
    输出样例#1: 复制
    2

    说明

    n200000,K1000000 。

     

    题解:点分, 统计经过中心长度为k且边数最少的路径,对每条路径记录属于哪棵子树,一个子树不能合并,不合法;

    注意统计时的左右端点,zjj同学帮我调试了好久

    还有,洛谷上不开O2要RE?

    // luogu-judger-enable-o2
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    const int M = 200005, K = 1000001;
    struct ST{int dis, id, les;}tong[M];
    bool cmp(ST a, ST b){
        return a.dis < b.dis;
    }
    int n, tot, cnt, Ans = M, k, root, sum, h[M], siz[M], dis[M], f[M], dep[M];
    bool vis[M];
    struct edge{int v, nxt, w;}G[M<<1];
    void add(int u, int v, int w){
        G[++tot].v = v; G[tot].w = w; G[tot].nxt = h[u]; h[u] = tot;
    }
    void init(){
        memset(vis, 0, sizeof(vis));
        memset(h, 0, sizeof(h));
        tot = 0; Ans = K; sum = 0;
    }
    void getroot(int u, int fa){
        siz[u] = 1; f[u] = 0;
        for(int i = h[u]; i; i = G[i].nxt){
            int v = G[i].v;
            if(vis[v] || v == fa)continue;
            getroot(v, u);
            siz[u] += siz[v];
            f[u] = max(f[u], siz[v]);
        }
        f[u] = max(f[u], sum - siz[u]);
        if(f[u] < f[root]) root = u; 
        
    }
    
    void getdeep(int u, int fa, int zx){
        tong[++cnt].dis = dis[u];
        tong[cnt].id = zx;
        tong[cnt].les = dep[u];
        for(int i = h[u]; i; i = G[i].nxt){
            int v = G[i].v;
            if(vis[v] || v == fa)continue;
            dis[v] = dis[u] + G[i].w;
            dep[v] = dep[u] + 1;
            if(zx == -1)zx = u;    
            getdeep(v, u, zx);    
        }
    }
    
    
    void cal(int u, int ret){
        dis[u] = ret;
        dep[u] = 0;
        cnt = 0; 
        tong[++cnt].dis = dis[u];
        tong[cnt].id = u;
        tong[cnt].les = 0;
        for(int i = h[u]; i; i = G[i].nxt){
            int v = G[i].v;
            if(vis[v])continue;
            dis[v] = dis[u] + G[i].w;
            dep[v] = dep[u] + 1;
            getdeep(v, u, v);
            
        }
        sort(tong+1, tong+1+cnt, cmp);
        
        
        int lf = 1, rg = cnt;
        while(lf < rg){
            while(tong[lf].dis + tong[rg].dis < k && lf <= cnt)lf++;
            while(tong[lf].dis + tong[rg].dis > k && rg >= 1)rg--;
            if(lf >= cnt || rg <= 1 || lf >= rg)break;
            int llf = lf, rrg = rg;
            if(tong[lf].dis + tong[rg].dis == k){
                while(tong[llf].dis == tong[lf].dis && llf <= cnt)llf++;
                while(tong[rrg].dis == tong[rg].dis && rrg >= 1)rrg--;
                for(int i = lf; i < llf; i++)
                    for(int j = rrg+1; j <= rg; j++)
                        if(tong[i].id != tong[j].id)
                            Ans = min(Ans, tong[i].les + tong[j].les);
                lf = llf, rg = rrg;    
            }
            
        }
        
    }
    
    void solve (int u){
        cal(u, 0);
        vis[u] = 1;
        for(int i = h[u]; i; i = G[i].nxt){
            int v = G[i].v;
            if(vis[v])continue;
            sum = siz[v];
            getroot(v, root = 0);
            solve(root);
        }
    }
    
    
    int main(){
        f[0] = 1e9;
        scanf("%d%d", &n, &k);
        for(int i = 1; i < n; i++){
            int u, v, w;
            scanf("%d%d%d", &u, &v, &w);
            add(u + 1, v + 1, w); add(v + 1, u + 1, w);
        }
        sum = n;
        getroot(1, 0);    
        solve(root);
        if(Ans == M)printf("-1
    ");
        else printf("%d
    ", Ans);
    }
    View Code

    这几天没调出一道程序,都是zjj同学帮我的,怎么感觉代码水平越学越烂?

    2018-08-15 

  • 相关阅读:
    python字符编码与转码
    python字符编码与转码
    BlackNurse攻击:4Mbps搞瘫路由器和防火墙
    BlackNurse攻击:4Mbps搞瘫路由器和防火墙
    BlackNurse攻击:4Mbps搞瘫路由器和防火墙
    BlackNurse攻击:4Mbps搞瘫路由器和防火墙
    HTML基础
    HTML基础
    小伙做起石化贸易生意,他的创业之路不平坦
    种植苗木基地,村官靠这个成为致富好能手
  • 原文地址:https://www.cnblogs.com/EdSheeran/p/9483260.html
Copyright © 2011-2022 走看看