2019-10-06我还是不知道自己错在哪里了这让我很蛋疼……

2019-10-06我还是不知道自己错在哪里了这让我很蛋疼……

PAT A1004

A1004 Counting Leaves
简言之,就是找出树中的叶子(没有后代/子节点),然后我完全忘了BFS搜索和DFS搜索,就用普通方法做的,做完了觉得没啥毛病,能跑的例子也跑完了,就是不对……哎……
我的思路就很简单,根据父节点分层,判断子节点位于哪一层,在分层 过程中记录下哪些是子节点,那些是父节点,最后统计每层的叶子数。
贴个代码:

#include<cstdlib>
#include<iostream>
#include<string.h>
#include<algorithm>
using namespace std;

int main()
{
	int n, m;//n是结点数目 m是non-leaf结点
	cin >> n >> m;

	int id[100], k, i = 0;
	int floor[100];
	memset(floor, 0xff, 100);//初始化
	//cout << floor[0] << " " << floor[2] << endl;
	int count[100];
	memset(count, 0, sizeof(count));//初始化
	int is_root[100];//1为fu节点
	memset(is_root, 0, 100);
	int father[100];//记录父节点
	memset(father, 0xff, sizeof(father));
	int dad; int maxf = 0;
	int j = 0;

	while (m--)
	{
		cin >> i >> k;
		id[i] = k;//id数组里储存的是子结点数目
		if (floor[i] == -1)
			floor[i] = 0;//顶层
		if (k)//存在叶节点
		{
			is_root[i] = 1;//父节点
			dad = i;
			while (k--)
			{
				cin >> i;
				father[i] = dad;
				floor[i] = floor[dad] + 1;//子结点层数
				maxf = max(floor[i], maxf);
			}
		}
	}

	for (i = 1; i < n+1; i++)//节点从01开始
	{
		if (father[i] == -1 && is_root[i] == 0)//顶层
		{
			//cout << "count[0]++" << endl;
			count[0]++;
		}
		else if (is_root[i] == 0 && father[i] != -1)//非顶层
		{
			//cout << "floor=" << floor[father[i]]++ << endl;
			//cout << "count++" << endl;
			count[floor[father[i]]+1]++;
		}
	}

	if (maxf == 0)
	{
		cout << count[0];
		system("PAUSE");
		return 0;
	}

	for (j = 0; j<maxf ; j++)
	{
		cout << count[j] << " ";
	}
	cout << count[maxf];

	system("PAUSE");
	return 0;
}

纠正一个错误,之前说max函数是string.h头文件里面的,我记错了,应该是algorithm文件里面的,string.h头文件里的是memset函数。
然后还发现了一个神奇的问题,就是memset能初始化的只有0和-1???因为除了这两个,其余初始化全部失败,查到的资料也这么写,那么……我上一道题明明也用了啊……
刚才我又仔细看了看文章,memset函数是按照字节来赋值的

void *(memset)(void *s, int c, size_t n)
{
    const unsigned char uc = c;
    unsigned char *su;
    for (su = s; 0 < n; ++su, --n)
        *su = uc;
    return (s);
}

也就是它的值每次赋值给一个字节,而不是4个字节,c的类型是int类型,4个字节,但只会赋值最低位的一个字节的内容。
当c是1的时候,二进制低8位就是0000001,最终int类型数组一个元素的内容就变成了 0000001000000100000010000001,明显是个很大的数,而不是1。

int a[MAXN];
memset(a, 0, sizeof(a));//数组中的所有元素全为0
memset(a, -1, sizeof(a));//数组中的所有元素全为-1
memset(a, 127, sizeof(a));//数组中的所有元素全为2139062143(可以将其视为INF)

这是我查到的一些用法,用来说明memset不可任意赋值,还是for好用……如果是

int a[10]={0};

当初值全是0的时候,可以这么进行初始化,a中的全部元素都是0了。
回归正题,看了别人的正确算法,也算拓展了知识,一个大佬的优秀答案使用DFS算法,外加回溯……这种蛋疼的题很能提高自己的薄弱区间呢……我觉得应该多练练这个!
DFS深度优先 BFS广度优先
显然这道题更适合深度优先。
代码很好懂:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<vector>
using namespace std;
int n,m,mx=-1;
vector <int> vc[120];
int vis[120];
void dfs(int x,int le)
{
	if(vc[x].size()==0)
	{
		vis[le]++;
		mx=max(mx,le);
		return ;
	}
	for(int i=0;i<vc[x].size();i++)
	{
		dfs(vc[x][i],le+1);
	}
}
int main(void)
{
	int i,j,k,zi,fu;
	scanf("%d %d",&n,&m);
	memset(vis,0,sizeof(vis));
	for(i=1;i<=m;i++)
	{
		scanf("%d %d",&fu,&k);
		for(j=1;j<=k;j++)
		{
			scanf("%d",&zi);
			vc[fu].push_back(zi);
		}
	}
	
	dfs(1,0);
	for(i=0;i<=mx;i++)
	{
		if(i==0) printf("%d",vis[i]);
		else printf(" %d",vis[i]);
	}
	return 0;
}

构建了一个vector容器,每个父节点下的成员是它的子结点,进而可以一步步往下算,这种方法学到了!期待下次好好使用!
加油加油加油!!
第一次用markdown编辑,有点爽啊哈哈哈哈哈!

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值