作为绿色的使者,小h有棵nn个节点的带权树。
找出kk个点A1,A2,⋯,AkA1,A2,⋯,Ak。
使得∑k−1i=1dis(Ai,Ai+1)∑i=1k−1dis(Ai,Ai+1)最小。
其中dis(i,j)dis(i,j)表示点ii到点jj的树上最短路。
输入格式
第一行两个正整数n,kn,k,表示树的顶点数和需要选出的点个数。
接下来n−1n−1行每行33个非负整数x,y,zx,y,z,表示从存在一条从xx到yy权值为zz的边。
1≤k≤n1≤k≤n。
1≤x,y≤n1≤x,y≤n。
1≤z≤1051≤z≤105。
输出格式
一行一个整数,表示最小的距离和。
样例一
input
5 4 1 2 1 2 3 3 2 4 2 4 5 5
output
7
数据范围
对于10%10%的数据, n≤10 n≤10。
对于另外10%10%的数据, k=n k=n。
对于另外20%20%的数据, n≤50 n≤50。
对于另外20%20%的数据, n≤200 n≤200。
对于100%100%的数据, n≤3000 n≤3000。
时间限制:1s1s
空间限制:256MB
思路:由于当n=k的时候,答案就是边长的两倍减去直径。
由于n最多只有3000,所以我们做一个树形dp。
dp[i][j][0]表示以i为根的子树中选择了j个点作为联通块,最小的总边长的两倍
dp[i][j][1]表示以i为根的子树中选择了j个点作为联通块,当直径是i到下面的某个点时候的答案
dp[i][j][2]表示以i为根的子树中选择了j个点作为联通块,此时的答案。
时间复杂度:O(N^2),感觉这个时间复杂度不是很对啊!!!orz
1 #include<bits/stdc++.h> 2 3 using namespace std; 4 5 #define F(i,a,b) for(int i=a;i<=b;i++) 6 #define D(i,a,b) for(int i=a;i>=b;i--) 7 #define ms(i,a) memset(a,i,sizeof(a)) 8 9 template <class T> void read(T &x){ 10 x=0; int w=0; char c=getchar(); 11 while (c<'0' || c>'9' ) w+=c=='-',c=getchar(); 12 while (c>='0' && c<='9') x=(x<<3)+(x<<1)+(c^48),c=getchar(); 13 if(w) x=-x; 14 } 15 16 template <class T> void chkmin(T &x,T y) {x=min(x,y);} 17 template <class T> void chkmax(T &x,T y) {x=max(x,y);} 18 19 template <class T >void write( T x){ 20 if(x<0) x=-x,putchar('-'); 21 if(x>9) write(x/10); 22 putchar(x% 10+48); 23 } 24 25 template <class T >void writeln(T x){ 26 write(x); 27 putchar('\n'); 28 } 29 int const maxn=3003; 30 int const inf=1e9; 31 struct Edge{ 32 int to,nt,w; 33 }E[maxn<<1]; 34 35 int n,k,sz[maxn],dp[maxn][maxn][3],H[maxn],cnt; 36 37 void add(int a,int b,int c){ 38 E[cnt]=(Edge){b,H[a],c}; H[a]=cnt++; 39 } 40 41 void merge(int x,int y,int len){ 42 F(i,sz[x]+1,sz[x]+sz[y]) dp[x][i][0]=dp[x][i][1]=dp[x][i][2]=inf; 43 D(i,sz[x],1) F(j,1,sz[y]){ 44 chkmin(dp[x][i+j][0],dp[x][i][0]+dp[y][j][0]+len*2); 45 chkmin(dp[x][i+j][1],dp[x][i][1]+dp[y][j][0]+len*2); 46 chkmin(dp[x][i+j][1],dp[x][i][0]+dp[y][j][1]+len); 47 chkmin(dp[x][i+j][2],dp[x][i][2]+dp[y][j][0]+len*2); 48 chkmin(dp[x][i+j][2],dp[x][i][1]+dp[y][j][1]+len); 49 chkmin(dp[x][i+j][2],dp[x][i][0]+dp[y][j][2]+len*2); 50 } 51 sz[x]+=sz[y]; 52 } 53 void dfs(int x,int fa){ 54 sz[x]=1; 55 for(int i=H[x];i!=-1;i=E[i].nt){ 56 int v=E[i].to; 57 if(v==fa) continue; 58 dfs(v,x); 59 merge(x,v,E[i].w); 60 } 61 } 62 int main(){ 63 read(n); 64 read(k); 65 ms(-1,H); 66 F(i,1,n-1){ 67 int x,y,z; 68 read(x);read(y); read(z); 69 add(x,y,z); 70 add(y,x,z); 71 } 72 dfs(1,1); 73 int ans=inf; 74 F(i,1,n) if(sz[i]>=k) chkmin(ans,dp[i][k][2]); 75 writeln(ans); 76 return 0; 77 }