2019-10-06我还是不知道自己错在哪里了这让我很蛋疼……
PAT A1004
简言之,就是找出树中的叶子(没有后代/子节点),然后我完全忘了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编辑,有点爽啊哈哈哈哈哈!