1. 程式人生 > >[BZOJ3829][Poi2014]FarmCraft 貪心

[BZOJ3829][Poi2014]FarmCraft 貪心

amp cto getchar char push %d tdi sta sin

這個題應該是很容易想到貪心的,只要可是怎麽貪才是科學的呢?
我們分析一下題幹,對於每個邊只能一進一出因此,對於樹上的一棵子樹,我們只要一進子樹就必須遍歷完,
因此我們只能進行一遍 dfs() 然後我們發現 dfs() 一遍的時間是一定的,
然後見每個妹子的時間就在這個時間軸上,
分析完了,我們說一下要貪什麽。
我們先定義一個概念rest[]就是遍歷完這個節點的子樹以後我們還要為這個節點所費的時間
One_Stage :除了1節點,之外每個妹子一見面就殺du
Two_Stage :我們發現最後的答案是 Max(rest[1],c[1])+2*n-2
Three_Stage :然後我們考慮怎麽找rest[1],
我們發現每個節點的最優rest[],是(子節點的rest[],減去其在這個子樹裏又經過的時間),再和(他的c[]減去遍歷他的時間)取Max
這樣我們線性一波就結局了

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#define MAXN 500005
using namespace std;
inline int read()
{
  register int sum=0;
  register char ch=getchar();
  while(ch<0||ch>9)ch=getchar();
  while(ch>=0&&ch<=9)
  {
    sum
=(sum<<1)+(sum<<3)+ch-0; ch=getchar(); } return sum; } inline int Max(int x,int y) { return x>y?x:y; } int a[MAXN],m[MAXN],n,t[MAXN]; vector<int> Via[MAXN]; void Dfs_T(int x,int fa) { register int len=Via[x].size(); for(register int i=0;i<len;++i) if(Via[x][i]!=fa) { Dfs_T(Via[x][i],x); t[x]
+=2+t[Via[x][i]]; } } inline void Init() { n=read(); for(register int i=1;i<=n;i++)a[i]=read(); for(register int i=1,x,y;i<n;i++)x=read(),y=read(),Via[x].push_back(y),Via[y].push_back(x); Dfs_T(1,0); } int rest[MAXN]; int comp(const int x,const int y) { return rest[x]>rest[y]; } inline void Dfs_A(int x,int fa) { register int len=Via[x].size(); for(register int i=0;i<len;++i) if(Via[x][i]!=fa)Dfs_A(Via[x][i],x); sort(Via[x].begin(),Via[x].end(),comp); if(x!=1)rest[x]=a[x]-t[x]; register int now=t[x]; for(register int i=0;i<len;i++) if(Via[x][i]!=fa) { now-=2+t[Via[x][i]]; rest[x]=Max(rest[x],rest[Via[x][i]]-now-1); } if(rest[x]<0)rest[x]=0; } inline void Work() { Dfs_A(1,0); register int ans=Max(rest[1],a[1])+t[1]; printf("%d",ans); } int main() { Init(); Work(); return 0; }

[BZOJ3829][Poi2014]FarmCraft 貪心