• “玲珑杯”ACM比赛 Round #18 1147


    题目链接:http://www.ifrog.cc/acm/problem/1147

    题解:这题很容易想到的是边的贡献也就是每条边最多被取到几次,和点的贡献类似,那些加边只要加在边贡献大的边上就行。然后什么是边的贡献,就是一条边左右两边连着的最小的点的个数,因为这条边最多被取到这么多次。还有就是爆栈的处理具体看一下代码那个define的就是爆栈的处理如果是lunix的话那个else不需要。

    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #include <algorithm>
    #include <cstdlib>
    #include <cstring>
    #include <cassert>
    #define inf 0X3f3f3f3f
    #define OPENSTACK
    using namespace std;
    const int M = 1e5 + 10;
    typedef long long ll;
    struct TnT {
        int v , next , w;
    }edge[M << 1];
    struct GBA {
        ll val , pos;
        int num;
    }GG[M];
    int e , head[M] , n , k , in[M] , cnt;
    ll c[M];
    bool cmp(GBA x , GBA y) {
        return x.num > y.num;
    }
    void init() {
        e = 0, cnt = 0;
        memset(head , -1 , sizeof(head));
        memset(in , 0 , sizeof(in));
    }
    void add(int u , int v , int w) {
        edge[e].v = v;
        edge[e].w = w;
        edge[e].next = head[u];
        head[u] = e++;
    }
    ll dfs(int u , int pre) {
        ll sum = 1;
        for(int i = head[u] ; i != -1 ; i = edge[i].next) {
            int v = edge[i].v;
            if(v == pre) continue;
            ll ans = dfs(v , u);
            GG[cnt].num = min(ans , (ll)n - ans), GG[cnt++].val = edge[i].w;
            sum += ans;
        }
        return sum;
    }
    int main() {
    #ifdef OPENSTACK
        int size = 64 << 20; // 64MB
        char *p = (char*)malloc(size) + size;
    #if (defined _WIN64) or (defined __unix)
        __asm__("movq %0, %%rsp
    " :: "r"(p));
    #else
        __asm__("movl %0, %%esp
    " :: "r"(p));
    #endif
    #endif
        int t;
        scanf("%d" , &t);
        while(t--) {
            scanf("%d%d" , &n , &k);
            init();
            for(int i = 1 ; i < n ; i++) {
                int u , v , w;
                scanf("%d%d%d" , &u , &v , &w);
                add(u , v , w);
                add(v , u , w);
                in[u]++, in[v]++;
            }
            for(int i = 0 ; i < k ; i++) scanf("%lld" , &c[i]);
            for(int i = 1 ; i <= n ; i++) {
                if(in[i] == 1) {
                    dfs(i , -1);
                    break;
                }
            }
            sort(GG , GG + n , cmp);
            sort(c , c + k);
            reverse(c , c + k);
            ll ans = 0;
            for(int i = 0 ; i < k ; i++) {
                ans += GG[i].num * (GG[i].val + c[i]);
            }
            for(int i = k ; i < cnt ; i++) ans += GG[i].num * GG[i].val;
            printf("%lld
    " , ans);
        }
    #ifdef OPENSTACK
        exit(0);
    #else
        return 0;
    #endif
    }
  • 相关阅读:
    Squid报错:error the requested url could not be retriveved
    理解交换机的工作原理
    1_bytes和str
    2_Linux操作系统和基础命令行
    1_Linux概述
    好用的手机浏览器
    笔记(一):做前端开发以来几乎每天用到的东西!
    笔记(一):做前端开发以来几乎每天用到的东西!
    积累: .net里有个线程安全的int+1类
    积累: .net里有个线程安全的int+1类
  • 原文地址:https://www.cnblogs.com/TnT2333333/p/7192854.html
Copyright © 2020-2023  润新知