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

来源:互联网 发布:传输文件到阿里云 编辑:程序博客网 时间:2024/06/04 18:09

题目描述

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最少需要耗费的时间

样例

样例输入

51 2 12 3 13 4 11 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)

数据范围

测试点范围301<=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;}



原创粉丝点击