[吼吼]加工树枝

作者:雲中君 | 出处:博客园 | 2011/12/7 23:39:37 | 阅读 7

【描述】

Dragon同学一天捡到了一根非常非常巨大的树枝,于是同学就想啊,如果把这根树枝多余的分叉剔掉最后剩下一根没有分叉的木棍,用它自卫就没人敢欺负我们科学家了呀:)

你的任务是,对给定树枝,求出它包含的最长木棍。

【输入格式】

第一行一个正整数n,表示顶点数,顶点从1至n编号。

然后n – 1行每行两个正整数u, v表示u, v之间有一条边,每条边的长度为1。

保证输入的是一棵树。

【输出格式】

只有一行,表示给定树的最长链长度。

【样例输入】

5

1 2

1 3

1 4

1 5

【样例输出】

2

【分析】

很明显,求树中的最长链。设f[i]是i的子树中最远的点到自己的距离,p[i]是第二远的点到自己的距离。那么所有的点钟最大的f[i]+p[i]就是答案。

第一次写——临边表。显然存不下。

第二次写——模拟链表。用的递归造树,爆掉。

想到了要用手工的栈。

可是我不知道怎么写囧。

于是看了标程。

原来还可以这么构树!!!

原来手工栈这么写!!!

顿悟。

第三次——AC。

 

 
01
#include <stdio.h>
02
#include <stdlib.h>
03
#define maxn 1000010
04

05
int f[maxn];
06
int father[maxn],str[maxn];
07
struct ss
08
{
09
int num,next;
10
} a[maxn];
11
int tot,n,u,v,p,ans;
12
int c[maxn],deep[maxn],sta[maxn],top,e[maxn],te;
13

14
void ins(int x,int y)
15
{
16
a[++tot].num=y;
17
a[tot].next=str[x];
18
str[x]=tot;
19
}
20

21
int cmp(const void*a,const void*b)
22
{
23
int c=*(int*)a,d=*(int*)b;
24
if (deep[c]<deep[d]) return -1;
25
if (deep[c]>deep[d]) return 1;
26
return 0;
27
}
28

29
int main()
30
{
31
freopen("tree.in","r",stdin);
32
freopen("tree.out","w",stdout);
33

34
scanf("%d",&n);
35
for (int i=1;i<n;++i)
36
{
37
scanf("%d%d",&u,&v);
38
ins(u,v);
39
ins(v,u);
40
}
41

42
sta[0]=1;
43
e[0]=str[1];
44
father[1]=0;
45
while (top>=0)
46
{
47
te=e[top];
48
if (!te) --top;
49
else
50
{
51
v=sta[top];
52
u=a[te].num;
53
e[top]=a[te].next;
54
if (u!=father[v])
55
{
56
sta[++top]=u;
57
e[top]=str[u];
58
deep[u]=deep[v]+1;
59
father[u]=v;
60
}
61
}
62
}
63

64
for (int i=1;i<=n;++i) c[i]=i;
65
deep[0]=-1;
66
qsort(c,n+1,sizeof(int),cmp);
67
for (int i=n;i>0;--i)
68
{
69
u=c[i];
70
te=str[u];
71
if (!te) continue;
72
p=0;
73
do
74
{
75
v=a[te].num;
76
if (father[u]!=v)
77
if (f[v]+1>f[u])
78
{
79
p=f[u];
80
f[u]=f[v]+1;
81
}
82
else
83
if (f[v]+1>p) p=f[v]+1;
84
te=a[te].next;
85
}
86
while (te);
87
if (f[u]+p>ans) ans=f[u]+p;
88
}
89

90
printf("%d\n",ans);
91

92
return 0;
93
}

转载于:https://www.cnblogs.com/pengyingh/articles/2388941.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值