Gebecr与KZime的膜你赛kZime与Git解题报告

题目描述

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
1<=n<=1000000 题解: 树形dp 令f[x]为处理x为根子树最小代价 那么f[x]=min(f[u]+summ[x]-summ[u]-v[x])u为x的儿子 时空复杂度均为O(n) 代码:
#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;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值