“喜闻乐见”的遇到BUG。。。
简单的想法就是DFS或者BFS。也可以先用并查集找出树的棵数。我采用了后者,代码结构更清晰。
总共遇到两个BUG,一个是大数据的CASE出错,另一个是第三个CASE出错。
前一个是因为把长度为n的数组定义在了函数内,造成在n接近10^4时出错,应该是数组大小超出了函数可使用的堆大小。经测试,64位ubuntu+gcc 4.8.2下,main函数内在定义2^20 int数组(大约4MB)时运行正常,但在2^21(大约2*10^6)时出现“Segmentation fault”。而非main函数在2^20时就会出错,2^19时不会。
第二个是在find函数里,pointto[fl] = nr。这句在循环图里会产生错误:
5
1 2
2 3
3 4
4 1
这种情况程序会判断只有1棵树,因为pointto数组是“4 4 4 1 5",还少一次更新。正确的写法应该是pointto[fl] = fr;
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <assert.h>
int n;
typedef struct s_link{
int to;
struct s_link *nx;
}Link; // adjacency link
Link link[10001];
int pointto[10001];
int roots[10001], pr;
int maxDepth;
bool bv[10001];
int dfs(int root);
int cmp(const void *pvl, const void *pvr)
{
return *((int*)pvl) - *((int*)pvr);
}
int find(int num)
{
if(pointto[num] == num) return num;
else return pointto[num] = find(pointto[num]);
}
void merge(int nl, int nr)
{
int fl = find(nl), fr = find(nr);
pointto[fl] = fr;
#ifdef DEBUG
int i;
for(i=1; i<=n; ++i)
printf("%d ", pointto[i]);
printf("\n");
#endif
}
int main(void)
{
#ifdef DEBUG
freopen("in.txt", "r", stdin);
#endif
scanf("%d", &n);
int i, j;
for(i=1; i<=n; ++i)
pointto[i] = i;
for(i=1; i<n; ++i){
int x, y;
scanf("%d%d", &x, &y);
if(x == y) continue;
merge(x, y);
Link *pl = (Link*)malloc(sizeof(Link));
pl->to = y;
pl->nx = link[x].nx;
link[x].nx = pl;
pl = (Link*)malloc(sizeof(Link));
pl->to = x;
pl->nx = link[y].nx;
link[y].nx = pl;
}
int cnt=0;
for(i=1; i<=n; ++i)
if(pointto[i] == i)
cnt++;
if(cnt > 1){
printf("Error: %d components\n", cnt);
return 0;
}
for(i=1; i<=n; ++i){ // DFS from every node
for(j=1; j<=n; ++j)
bv[j] = false;
int depth = dfs(i);
if(depth > maxDepth){
maxDepth = depth;
roots[0] = i;
pr = 1;
}
else if(depth == maxDepth)
roots[pr++] = i;
}
// output
qsort(roots, pr, sizeof(int), cmp);
for(i=0; i<pr; ++i)
printf("%d\n", roots[i]);
return 0;
}
int dfs(int root)
{
Link *pl = link[root].nx;
int depth = 0, maxd = 0;
bv[root] = true;
while(pl != NULL){
if(!bv[pl->to]){
depth = dfs(pl->to);
if(maxd < depth)
maxd = depth;
}
pl = pl->nx;
}
return maxd+1;
}