还没看完整个题目,我就想到:啊,树的最长路!
于是我就轻率地写了个树的最长路的算法,严重TLE。因为每求一次的时间是O(n),k次就是O(n*k),要是n跟k都大(一开始忘了这一点),就成了跟o(n^2)差不多了。跟最笨的算法——从每个节点出发做一次DFS是一个等级的。
附:第一版TLE代码:
儿子兄弟表示法+改进树的最长路
于是我就看了Analysis。
大概是这么说的:
1.先找到每个党在树中最深的节点。它一定是最长的路的一端。 (orz这个想法,太巧了,有点像某年noip的树网的核一样巧……)
2.用tarjan算法求LCA。这里的LCA就是这个点与该党最深的节点间的最近公共祖先。
在tarjan(x)中,如果x是该党最深节点,则用它来更新所有该党的节点的LCA;
如果x不是 该党最深节点,就用该党最深节点来更新它。
3.x,y距离=depth(x)+depth(y)-2*(LCA(x,y))
优化后代码如下:
结果还是TLE。
我发现我犯傻了……枚举每个党的成员的时候不应该从1到n枚举然后判断,而是应该先存到一个邻接表里面。(用vector实现)
第三版:
但是不知道为什么,交上去在第12、13个测试数据会有segmentation fault,而在我的机器上跑的好好的,答案也对,而且我开的空间远远没有MLE。我为了弄清问题,从windows换到了linux,也run的好好的。莫非usaco的机器问题?呃……罢了罢了……就当我Ac了算了-_-!
> Run 1: OK [0.000 secs, 11608 KB]
> Run 2: OK [0.000 secs, 11608 KB]
> Run 3: OK [0.000 secs, 11608 KB]
> Run 4: OK [0.011 secs, 11608 KB]
> Run 5: OK [0.022 secs, 11636 KB]
> Run 6: OK [0.086 secs, 11608 KB]
> Run 7: OK [0.335 secs, 11872 KB]
> Run 8: OK [0.151 secs, 17656 KB] > Run 9: OK [1.112 secs, 19200 KB]
> Run 10: OK [0.259 secs, 11608 KB]
> Run 11: OK [0.346 secs, 12812 KB]
> Run 12: Execution error: Your program had this runtime error:
Exceeded memory or invalid memory reference. The program ran for
0.302 CPU seconds before the error. It used 12796 KB of memory.
> Run 13: Execution error: Your program (`cowpol') exited with signal #11 (segmentation violation [maybe caused by accessing
memory out of bounds, array indexing out of bounds, using a bad
pointer (failed open(), failed malloc), or going over the maximum
specified memory limit]). The program ran for 0.292 CPU seconds
before the signal. It used 12664 KB of memory.