【树形结构-贪心】多校联考No.2——energy

前言

果然一般前一场发挥好了,这一场就会以各种奇怪的方式爆掉...qwq...玄学

考后看了题记和标程,发现自己的做题的思路没有正解巧妙,代码也更冗长,思维和实现上确实还需要提高... ...

时间关系,正解就不说了,只说自己的考试思路

贴一个题解:

https://blog.csdn.net/eric1561759334/article/details/77587219

这次考试特别奇怪的就是——感觉自己的方法就是正解,不知道哪里有缺陷qwq... ...改完题后还是这样觉得...有待继续思考探究

题目

Sample Input

4 0 3 2

0 100 100

1 1 1

2 75 80

Sample Output

2

【数据范围】

对于 100%的数据,满足 1<=n<=1000,0<=Fi<=n,0<=Ei,Wi<=100

分析

第一看以为是网络流一类的题,狂汗...

考试时自己感觉就是个暴搜,果断写了两个dfs

dfs1:回溯式搜索出每条边“需要通过的”或“可以通过的”能量值

例如对于节点u到其father的一条边,它通过的能量值就是min(往下搜出的能量值+当前节点需要的能量值e边u-fa允许通过的最大能量值)

dfs2:统计能得到足够能量的节点个数

说实话,不是很懂为什么得了0分... ...

考试暴零代码

#include<cstdio>
#include<cmath>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int MAXN=2000,INF=1e9;
int head[MAXN+5];
int n,cnt,ans;
struct edge
{
	int u,v,e,w;//e是节点v的
	int next;
}E[MAXN+5];
void addedge(int u,int v,int e,int w)
{
	E[++cnt].u=u;
	E[cnt].v=v,E[cnt].e=e,E[cnt].w=w;
	E[cnt].next=head[u];
	head[u]=cnt;
}
int dfs1(int u,int fa)
{
	int Min=0;
	for(int i=head[u];i;i=E[i].next)
	{
		int v=E[i].v;
		Min+=dfs1(v,u);
	}
	for(int i=head[fa];i;i=E[i].next)
	{
		int v=E[i].v;
		if(v==u)
		{
			if(Min==0)//叶节点 
				return E[i].w;
			return min(Min+E[i].e,E[i].w);
		}
	}
}
void dfs2(int u,int fa,int Min)
{
	int tmp=INF,f;
	for(int i=head[fa];i;i=E[i].next)
	{
		int v=E[i].v;
		if(v==u)
		{
			tmp=E[i].e;
			f=E[i].w;
			break;
		}
	}
	if(tmp<=Min&&f>=tmp)
		ans++;
	for(int i=head[u];i;i=E[i].next)
	{
		int v=E[i].v;
		if(tmp<=Min&&f>=tmp)
			dfs2(v,u,min(f,Min-tmp));
		else
			dfs2(v,u,min(f,Min));
	}
}
int main()
{
	//freopen("energy.in","r",stdin);
	//freopen("energy.out","w",stdout);
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	{
		int f,e,w;
		scanf("%d%d%d",&f,&e,&w);
		addedge(f,i,e,w);
	}
	for(int i=head[0];i;i=E[i].next)
	{
		int lim=dfs1(E[i].v,0);
		dfs2(E[i].v,0,lim);
	}	
	printf("%d",ans);
	return 0;
}
/*
根节点编号为0 
5
0 100 170
0 5 10
1 50 40
2 5 5
3 20 20
ans:4

6
0 10 30
0 5 70
1 20 20
2 20 60
4 30 30
4 10 5
ans:5
*/

AC代码

#include<cstdio>
#include<cmath>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int MAXN=1000;
int fa[MAXN+5],w[MAXN+5];
int n,ans;
struct node
{
	int id,e;
}p[MAXN+5];
bool cmp(node a,node b)
{
	return a.e<b.e;
}
int main()
{
	//freopen("energy.in","r",stdin);
	//freopen("energy.out","w",stdout);
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	{
		scanf("%d%d%d",&fa[i],&p[i].e,&w[i]);
		p[i].id=i;
	}
	sort(p+1,p+n+1,cmp);
	for(int i=1;i<=n;i++)
	{
		int j;
		for(j=p[i].id;j;j=fa[j])
			if(w[j]<p[i].e)
				break;
		if(j)
			continue;
		ans++;
		for(j=p[i].id;j;j=fa[j])
			w[j]-=p[i].e;
	}
	printf("%d",ans);
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值