鸽了两天,还是我太蒟了,mayan游戏调不出来,难题又不会,只有刷水DFS才能勉强维持一下生计这样子,我还是要提高姿势水平啊!
题目描述:
给定一棵树,每条边有边权,每个点有点权,如果某个点到其子节点的距离>子节点的点权,就删去该子节点以及其所有子节点,要求删去几个点;
题解:
很明显的水DFS;
暴力DFS每个节点,记录所有点到当前节点的最大距离(这里用了贪心,到父节点最长的距离+到该子节点的距离一定是最长的距离);
在用一个数记录这个点(或其父节点)是否要删去,如果要删去,就++ans;
坑点:
1、数组一定要开大!不然会RE;
2、某个点到其子节点的距离>子节点的点权才删去,是>没有=!
附上丑陋的代码:
1 #include<cstdio> 2 #include<algorithm> 3 using namespace std; 4 #define int long long 5 const int MAXM=1000001; 6 int n,k,first[MAXM],next[MAXM],last[MAXM],point[MAXM],top,ans; 7 bool bo[MAXM]; 8 struct Edge 9 { 10 int en,len; 11 }edge[MAXM]; 12 void add(int x,int y,int z) 13 { 14 ++top; 15 if(first[x]==0) first[x]=top; else next[last[x]]=top; 16 last[x]=top; 17 edge[top].en=y; 18 edge[top].len=z; 19 } 20 void dfs(int x,__int64 y,int z) 21 { 22 if(bo[x]) return; 23 bo[x]=true; 24 if(y>point[x]) 25 z=1; 26 if(z==1) 27 ++ans; 28 for(int i=first[x];i;i=next[i]) 29 { 30 dfs(edge[i].en,max(edge[i].len,y+edge[i].len),z); 31 } 32 } 33 main() 34 { 35 scanf("%lld",&n); 36 for(int i=1;i<=n;++i) 37 scanf("%lld",&point[i]); 38 for(int i=1;i<=n-1;++i) 39 { 40 int x=i+1,y,z; 41 scanf("%lld%lld",&y,&z); 42 add(x,y,z); 43 add(y,x,z); 44 } 45 dfs(1,0,0); 46 printf("%lld",ans); 47 return 0; 48 }