题目描述
kZime正致力于他的开源项目OALJ
他使用Git来管理他的代码,这是因为Git开分支非常方便,可以随便开很多个。
为了体现这一特性,kZime开了大量的分支,来满足他的需要,同时,由于kZime希望有多个任务并行操作,所以不存在两个分支在合并后是fast forward
的,换句话说,如果两个分支在合并后是fast forward
的,那么我们认为他们是一个分支。
经过各种魔幻操作之后,最后呈现在他眼前的是一颗无比复杂的版本继承树。由于kZime还要把这个项目放到Github上,如此复杂的继承关系和如此多的分支会令人无所适从。所以他决定将所有分支合并到master
分支上(注意:此处的“合并”并不是指git merge
)。但是不巧的是,由于他对于Git的某些特性走火入魔,导致连最基本的git merge
命令都不会使用了,他决定使用git rebase
来完成这个操作。
但是kZime足足写了一吨的代码,而他的电脑跑的却比BZOJ的评测机还慢,执行如此之多的操作相当浪费时间,在查阅资料(口胡)后,他了解到,如果一个commit中修改了个文件,那么对这个commit进行一次git rebase
将耗费个单位的时间。如果一个分支中有个commit,那么对这个分支进行一次git rebase
将耗费个单位的时间。现在,他想知道,如果想要完成他的操作,最少需要耗费多少时间。
输入格式
第一行一个整数,表示一共有个commit
接下来行,每行三个整数。表示kZime基于版本 commit了一次,得到了版本,修改了个文件
特别的,我们认为所有的commit都基于,且没有修改任何文件。
输出格式
一行一个整数,表示kZime最少需要耗费的时间
样例
样例输入
5 1 2 1 2 3 1 3 4 1 1 5 2
样例输出
2
解释
1(1) | \ 5(2) 2(1) | 3(1) | 4(1)
样例如图所示,只需在5
的位置进行一次git rebase
,即可将其“合并”到master
上
如下图所示
1(1) \ 2(1) | 3(1) | 4(1) | 5'(2)数据范围
测试点 | 范围 |
---|---|
30 | |
#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
using namespace std;
const int maxn=1000000+10;
vector<int>A[maxn];
long long summ[maxn];
long long f[maxn];
int v[maxn];
inline void dfs(int x,int fa){
int ok=0;
for(int i=0;i<A[x].size();i++){
int u=A[x][i];
if(u==fa)
continue;
ok=1;
dfs(u,x);
summ[x]+=summ[u];
}
for(int i=0;i<A[x].size();i++){
int u=A[x][i];
if(u==fa)
continue;
f[x]=min(f[x],f[u]+summ[x]-summ[u]);
}
summ[x]+=v[x];
if(!ok)
f[x]=0;
}
int main(){
freopen("a.in","r",stdin);
freopen("a.out","w",stdout);
memset(f,127/2,sizeof(f));
int n;
scanf("%d",&n);
int x,y;
v[1]=1;
for(int i=1;i<n;i++){
scanf("%d %d",&x,&y);
scanf("%d",&v[y]);
A[x].push_back(y);
A[y].push_back(x);
}
dfs(1,0);
printf("%lld\n",f[1]);
return 0;
}