1147 - 最后你還是AK了
Time Limit:5s Memory Limit:256MByte
DESCRIPTION
今天HH遇到了一顆樹,這個樹有n個點(n為偶數),每條邊都有一個長度l,現在HH想把這n個點兩兩匹配,匹配成n/2對點,然后我們將匹配后的n/2對點的距離求和,我們將所有匹配方案里距離和最大的那一個值定義為可愛值.
即我們將這n個點分成了
定義dis(x,y)為x到y的距離,那么可愛值為
max(∑n/2i=1dis(ai,bi))
現在HH為了使這顆樹變可愛,他可以使用k次膜法,第i次能使一條邊的長度增加ci,但是被膜過的邊就不能再被膜了,現在HH想知道使用了膜法以后,這顆樹的可愛值最多能是多少.
INPUT
第一行是一個整數
T(1≤T≤10),表示有
T組數據 對於每組數據輸入一行2個整數
n,k (1≤n≤105,0≤k≤n−1)表示這棵樹總共有
n個點,
HH可以使用
k次膜法. 接着一行
n−1行每行3個數:
u,v,w(1≤u,v≤n,1≤w≤105)表示在
u和
v之間有一條長度為
w的邊. 最后一行
k個整數,第
i個整數
ci(1≤ci≤105)表示第
i種膜法能使得某一條邊變長
ci 保證
n為偶數且給出的是一顆樹
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 }