玲瓏杯1147 - 最后你還是AK了


1147 - 最后你還是AK了

Time Limit:5s Memory Limit:256MByte

DESCRIPTION

今天HHHH遇到了一顆樹,這個樹有nn個點(nn為偶數),每條邊都有一個長度ll,現在HHHH想把這nn個點兩兩匹配,匹配成n/2n/2對點,然后我們將匹配后的n/2n/2對點的距離求和,我們將所有匹配方案里距離和最大的那一個值定義為可愛值.

即我們將這nn個點分成了

定義dis(x,y)dis(x,y)xxyy的距離,那么可愛值為

max(n/2i=1dis(ai,bi))max(∑i=1n/2dis(ai,bi))

現在HHHH為了使這顆樹變可愛,他可以使用kk次膜法,第ii次能使一條邊的長度增加cici,但是被膜過的邊就不能再被膜了,現在HHHH想知道使用了膜法以后,這顆樹的可愛值最多能是多少.

INPUT
第一行是一個整數 T(1T10)T(1≤T≤10),表示有 TT組數據 對於每組數據輸入一行2個整數 n,k (1n105,0kn1)n,k (1≤n≤105,0≤k≤n−1)表示這棵樹總共有 nn個點, HHHH可以使用 kk次膜法. 接着一行 n1n−1行每行3個數: u,v,w(1u,vn,1w105)u,v,w(1≤u,v≤n,1≤w≤105)表示在 uuvv之間有一條長度為 ww的邊. 最后一行 kk個整數,第 ii個整數 ci(1ci105)ci(1≤ci≤105)表示第 ii種膜法能使得某一條邊變長 cici 保證 nn為偶數且給出的是一顆樹
OUTPUT
每組數據輸出一行,一個整數,表示♂可♂愛♂值♂最多能是多少
SAMPLE INPUT
1 4 2 1 2 5 2 3 5 3 4 5 5 5
SAMPLE OUTPUT
35
HINT
對於樣例,我們將1和4匹配,2和3匹配,然后對2和3之間的邊使用膜法,對3和4之間的邊使用魔法 若出現爆棧問題,改棧方法請參考1093題目代碼 1093地址:http://www.ifrog.cc/acm/problem/1093 代碼地址:http://ideone.com/Wk24ET
分析:不考慮加魔法時與加魔法是獨立的;
   不加魔法時貪心的對每條邊算貢獻為min(son[x] , n - son[x] )*len ,可以想象一下是可行的;
   加入魔法時只需貪心的放min(son[x] , n - son[x] )大的邊即可;
代碼:
#define OPENSTACK
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <climits>
#include <cstring>
#include <string>
#include <set>
#include <bitset>
#include <map>
#include <queue>
#include <stack>
#include <vector>
#include <cassert>
#include <ctime>
#define rep(i,m,n) for(i=m;i<=(int)n;i++)
#define mod 1000000007
#define inf 0x3f3f3f3f
#define vi vector<int>
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define ll long long
#define pi acos(-1.0)
#define pii pair<int,int>
#define sys system("pause")
#define ls rt<<1
#define rs rt<<1|1
const int maxn=1e5+10;
const int N=5e2+10;
using namespace std;
ll gcd(ll p,ll q){return q==0?p:gcd(q,p%q);}
ll qmul(ll p,ll q,ll mo){ll f=0;while(q){if(q&1)f=(f+p)%mo;p=(p+p)%mo;q>>=1;}return f;}
ll qpow(ll p,ll q,ll mo){ll f=1;while(q){if(q&1)f=qmul(f,p,mo)%mo;p=qmul(p,p,mo)%mo;q>>=1;}return f;}
int n,m,k,t,son[maxn],c[maxn],id[maxn];
vi e[maxn];
vi f[maxn];
ll ret;
bool cmp(int x,int y){return min(son[x],n-son[x])>min(son[y],n-son[y]);}
void dfs(int x,int y)
{
    son[x]=1;
    int i;
    rep(i,0,e[x].size()-1)
    {
        int z=e[x][i],w=f[x][i];
        if(z==y)continue;
        dfs(z,x);
        ret+=1LL*min(son[z],n-son[z])*w;
        son[x]+=son[z];
    }
}
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\n" :: "r"(p));
        #else
            __asm__("movl %0, %%esp\n" :: "r"(p));
        #endif
    #endif
    int i,j;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&n,&k);
        rep(i,1,n)id[i]=i,e[i].clear(),f[i].clear(),son[i]=0;
        rep(i,1,n-1)
        {
            int x,y,z;
            scanf("%d%d%d",&x,&y,&z);
            e[x].pb(y);
            f[x].pb(z);
            e[y].pb(x);
            f[y].pb(z);
        }
        rep(i,1,k)scanf("%d",&c[i]);
        ret=0;
        dfs(1,0);
        sort(c+1,c+k+1,greater<int>());
        sort(id+1,id+n+1,cmp);
        rep(i,1,min(n,k))ret+=1LL*min(son[id[i]],n-son[id[i]])*c[i];
        printf("%lld\n",ret);
    }
    #ifdef OPENSTACK
        exit(0);
    #else
        return 0;
    #endif
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM