【清华集训2017模拟12.09】Tree
2017-12-19 16:59
375 查看
Description
Input
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
Data Constraint
f0[i][j]为i为根选了j个点,且当前的最长链的一个端点的i的2*边-链长的最小值
f1定义与f0相似,但是链不过端点(其实也可以过,但是不会比对应的f1更优,所以其实没有影响)
然后就按照链在子树内的情况讨论dp就可以了
看上去好像是n^3的,但是实际上复杂度是∑fa[x]=fa[y]size[x]∗size[y]把它拆开时候发现是n^2的
Input
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
Data Constraint
题解
设g[i][j] 为以i为根的子树选择了j个点,它们构成的虚树的总长的最小值f0[i][j]为i为根选了j个点,且当前的最长链的一个端点的i的2*边-链长的最小值
f1定义与f0相似,但是链不过端点(其实也可以过,但是不会比对应的f1更优,所以其实没有影响)
然后就按照链在子树内的情况讨论dp就可以了
看上去好像是n^3的,但是实际上复杂度是∑fa[x]=fa[y]size[x]∗size[y]把它拆开时候发现是n^2的
贴代码
#include<iostream> #include<algorithm> #include<cstdio> #include<cstring> #include<cmath> #define fo(i,a,b) for(i=a;i<=b;i++) #define fo1(i,b,a) for(i=b;i>=a;i--) #define min(x,y) ((x)<(y)?(x):(y)) #define ll long long using namespace std; const int maxn=3005; int fi[maxn],ne[maxn*2],dui[maxn*2],dui1[maxn*2],qc[maxn],s[maxn]; ll f0[maxn][maxn],f1[maxn][maxn],g[maxn][maxn]; int i,j,k,l,m,n,x,y,z,now; ll ans,b; void add(int x,int y){ if (fi[x]==0) fi[x]=++now; else ne[qc[x]]=++now; qc[x]=now; dui[now]=y; dui1[now]=z; } void dfs(int x,int y){ int i=fi[x]; s[x]=1; g[x][1]=f0[x][1]=f1[x][1]=0; while (i){ if (dui[i]==y){ i=ne[i]; continue; } dfs(dui[i],x); z=dui[i]; fo1(j,min(m,s[x]),1){ fo1(k,min(s[dui[i]],m-j),1){ f1[x][j+k]=min(f1[x][j+k],b*g[x][j]+f1[z][k]+b*dui1[i]); f1[x][j+k]=min(f1[x][j+k],f0[x][j]+f0[z][k]+dui1[i]); f1[x][j+k]=min(f1[x][j+k],f1[x][j]+b*g[z][k]+b*dui1[i]); f0[x][j+k]=min(f0[x][j+k],b*g[x][j]+f0[z][k]+dui1[i]); f0[x][j+k]=min(f0[x][j+k],f0[x][j]+b*g[z][k]+b*dui1[i]); g[x][j+k]=min(g[x][j+k],g[x][j]+g[z][k]+dui1[i]); } } s[x]=s[x]+s[dui[i]]; i=ne[i]; } } int main(){ freopen("tree.in","r",stdin); freopen("tree.out","w",stdout); scanf("%d%d",&n,&m); fo(i,1,n-1){ scanf("%d%d%d",&x,&y,&z); add(x,y); add(y,x); } memset(g,1,sizeof(g)); memset(f0,1,sizeof(f0)); memset(f1,1,sizeof(f1)); b=2; dfs(1,0); ans=min(f0[1][m],f1[1][m]); fo(i,2,n){ ans=min(ans,min(f0[i][m],f1[i][m])); } printf("%lld\n",ans); return 0; }
相关文章推荐
- JZOJ 5496. 【清华集训2017模拟12.09】Tree
- 【清华集训2017模拟12.09】塔
- 【JZOJ 5495】【清华集训2017模拟12.09】MiniumCut(最小割树)
- [JZOJ5495]【清华集训2017模拟12.09】MiniumCut
- 【JZOJ5316】【清华集训2017模拟8.19】merge
- JZOJ5483. 【清华集训2017模拟11.26】简单路径
- 【清华集训2017模拟】Sequence
- JZOJ 5483. 【清华集训2017模拟11.26】简单路径
- [JZOJ5500]【清华集训2017模拟12.10】营养餐
- 5296. 【清华集训2017模拟】Sequence 树套树
- 【清华集训2017模拟】Create
- [jzoj]5483. 【清华集训2017模拟11.26】简单路径
- 【JZOJ 5295】【清华集训2017模拟】Create
- jzoj5317 【清华集训2017模拟8.19】func (寻找性质)
- 【JZOJ5317】【清华集训2017模拟8.19】func
- JZOJ5484. 【清华集训2017模拟11.26】快乐树
- JZOJ 5485. 【清华集训2017模拟11.26】字符串
- JZOJ 5489. 【清华集训2017模拟11.28】海明距离
- jzoj5498 【清华集训2017模拟12.10】大佬的难题 巧妙容斥
- 【清华集训2017模拟】ces