bzoj 4987: Tree

 

4987: Tree

Time Limit: 10 Sec  Memory Limit: 256 MB
Submit: 51  Solved: 27
[Submit][Status][Discuss]

Description

从前有棵树。
找出K个点A1,A2,…,Ak。
使得∑dis(AiAi+1),(1<=i<=K-1)最小。
 

 

Input

第一行两个正整数n,k,表示数的顶点数和需要选出的点个数。
接下来n-l行每行3个非负整数x,y,z,表示从存在一条从x到y权值为z的边。
I<=k<=n。
l<x,y<=n
1<=z<=10^5
n <= 3000
 

 

Output

一行一个整数,表示最小的距离和。
 

 

Sample Input

10 7
1 2 35129
2 3 42976
3 4 24497
2 5 83165
1 6 4748
5 7 38311
4 8 70052
3 9 3561
8 10 80238

Sample Output

184524

 

 

#include<iostream>
#include<cstdio>
#include<cstring>
#define maxn 3010
using namespace std;
int head[maxn],num,sz[maxn],f[maxn][maxn][3];
struct node{int to,pre,v;}e[maxn*2];
void Insert(int from,int to,int v){
    e[++num].to=to;
    e[num].v=v;
    e[num].pre=head[from];
    head[from]=num;
}
void dfs(int x,int father){
    sz[x]=1;f[x][0][0]=f[x][0][1]=0;
    for(int i=head[x];i;i=e[i].pre){
        int to=e[i].to;
        if(to==father)continue;
        dfs(to,x);
        for(int j=sz[x]-1;j>=0;j--)
            for(int k=sz[to]-1;k>=0;k--)
                for(int l=2;l>=0;l--)
                    for(int m=l;m>=0;m--)
                    f[x][j+k+1][l]=min(f[x][j+k+1][l],f[x][j][l-m]+f[to][k][m]+e[i].v*(2-(m&1)));
        sz[x]+=sz[to];
    }
}
int main(){
    int n,k,x,y,z,ans=1<<30;
    scanf("%d%d",&n,&k);
    for(int i=1;i<n;i++){
        scanf("%d%d%d",&x,&y,&z);
        Insert(x,y,z);Insert(y,x,z);
    }
    memset(f,0x3f,sizeof(f));
    dfs(1,0);
    for(int i=1;i<=n;i++)
        for(int j=0;j<=2;j++)
        ans=min(ans,f[i][k-1][j]);
    printf("%d",ans);
    return 0;
}

 

posted @ 2018-04-17 21:23  Echo宝贝儿  阅读(131)  评论(0编辑  收藏