[补档][Poi2014]FarmCraft
[Poi2014]FarmCraft
题目
mhy住在一棵有n个点的树的1号结点上,每个结点上都有一个妹子。mhy从自己家出发,去给每一个妹子都送一台电脑,每个妹子拿到电脑后就会开始安装zhx牌杀毒软件,第i个妹子安装时间为Ci。树上的每条边mhy能且仅能走两次,每次耗费1单位时间。mhy送完所有电脑后会回自己家里然后开始装zhx牌杀毒软件。卸货和装电脑是不需要时间的。求所有妹子和mhy都装好zhx牌杀毒软件的最短时间。INPUT
第一行输入一个整数N,表示有N个结点第二行有N个整数C1,C2...Cn,Ci表示第i个妹子安装杀毒软件的时间接下来的N-1行,每行两个整数x,y,表示x与y之间有一条无向边OUTPUT
输出文件仅包含一行,一个整数表示让所有妹子和mhy装好杀毒软件的最短时间SAMPLE
INPUT
61 8 9 6 3 21 32 33 44 54 6OUTPUT
11
解题报告
翻译真累= =,原题英文版,结果发现翻译跟英文啥关系没有,就粘了翻译,然后发现输入格式跟输出格式都没有翻译,然后= =,然后我就强行翻译了一发= =
考试时打了个dfs,骗了5分- -
正解:
贪心。
我们分析题干,发现每条边只能过两次,也就是一进一出,那么我们进了一个点,我们就要遍历完整个子树,所以我们只能跑一遍dfs,然后我们发现dfs一遍的时间是一定的,那么见每个妹子的时间就在这个时间轴上。
我们定义一个数组rest,代表遍历完这个节店的子树,以后我们还要为这个节点所费的时间。
1. 除了1节点,见到一个妹子杀一下毒
2. 我们发现答案是Max(rest[1],c[1])+2×(n-1)
3. 我们考虑如何找rest,我们发现,每个节点的最优rest是 子节点的rest,减去其在这个子树里又经过的时间 再和 它的c减去遍历它的时间 取个Max
1 #include<algorithm> 2 #include<iostream> 3 #include<cstring> 4 #include<cstdio> 5 #include<vector> 6 using namespace std; 7 inline int read(){ 8 int sum(0); 9 char ch(getchar()); 10 for(;ch<'0'||ch>'9';ch=getchar()); 11 for(;ch>='0'&&ch<='9';sum=sum*10+(ch^48),ch=getchar()); 12 return sum; 13 } 14 int n; 15 int w[500001]; 16 int fa[500001],t[500001],rest[500001]; 17 inline int my_max(int a,int b){ 18 return a>b?a:b; 19 } 20 inline int my_min(int a,int b){ 21 return a<b?a:b; 22 } 23 vector<int>g[500001]; 24 inline bool cmp(const int &a,const int &b){ 25 return rest[a]>rest[b]; 26 } 27 inline void dfs(int u){ 28 int size(g[u].size()); 29 for(int i=0;i<size;i++){ 30 int e(g[u][i]); 31 if(e!=fa[u]){ 32 t[u]++; 33 fa[e]=u; 34 dfs(e); 35 t[u]++; 36 t[u]+=t[e]; 37 } 38 } 39 if(u!=1) 40 rest[u]=w[u]-t[u]; 41 int tmp(t[u]); 42 sort(g[u].begin(),g[u].end(),cmp); 43 for(int i=0;i<size;i++){ 44 int e(g[u][i]); 45 if(e!=fa[u]){ 46 tmp-=2+t[e]; 47 rest[u]=my_max(rest[u],rest[e]-tmp-1); 48 } 49 } 50 rest[u]=my_max(0,rest[u]); 51 // cout<<u<<' '<<w[u]<<' '<<rest[u]<<endl; 52 } 53 int main(){ 54 n=read(); 55 for(int i=1;i<=n;i++) 56 w[i]=read(); 57 for(int i=1;i<n;i++){ 58 int x(read()),y(read()); 59 g[x].push_back(y),g[y].push_back(x); 60 } 61 dfs(1); 62 printf("%d",my_max(rest[1],w[1])+(n<<1)-2); 63 }