[NKU]sweet @ Google && TopCoder && CodeForces

  BlogJava :: 首页 :: 联系 :: 聚合  :: 管理
  33 Posts :: 1 Stories :: 15 Comments :: 0 Trackbacks
所谓树的核,就是树的中心
中心是指到其它节点距离的最大值最小的节点
1 - 2 - 5
|   |
3   4

样例里的1和2就是这个树的中心……
本题是要找出树的所有中心
由于时限2S,ural的机器又快,节点数不过10000,N^2枚举+DFS验证是无压力的……
但是身为一个有志青年,是不能轻言满足的……

由于无根树不好办事,我们不妨令根为1;
然后采用两遍DFS的方法
第一次从根开始DFS,处理每个顶点最多能够沿DFS的方向走多远,直接DFS就行
(在下面程序保存为rdeep)
这一部分处理完了,接下来的部分是每个顶点向该点的父节点反着走,能走多远
(在下面程序保存为fdeep)
这里的处理方法是这样:假设现在是这样:A的父亲为FA,有子节点B,C,D,沿着B向下DFS能走距离Db,C:Dc,D:Dd;
那么由B反着走到A,然后再往远走,最远能到哪里呢?……有3个选择,沿着FA向上,沿着C向下,沿着D向下
选择一个最长的就行了;
假设某个节点的子节点数很多,实际上只用保留两种情况:能走最远的字节点,以及能走第二远的字节点;
其他字节点都往该节点父节点或者最远的子节点走;最远的那个往该节点父节点或者第二远的子节点走;

代码如下:
 

  1
 class Prob {
  2 //临接表
  3     ArrayList< LinkedList<Integer> > adj;
  4 //加速控制台IO
  5     BufferedReader br = new BufferedReader(
  6         new InputStreamReader(System.in));
  7 
  8 //计算正向DFS的最远深度
  9     int[] rdeep;
 10     int dfs(int now,int fa) {
 11         for (Integer i : adj.get(now)) {
 12             if (i == fa) continue;
 13             int tmp = dfs(i,now);
 14             if (tmp > rdeep[now]) {
 15                 rdeep[now] = tmp;
 16             }
 17         }
 18         return rdeep[now] + 1;
 19     }
 20 
 21 //反向DFS的深度
 22     int[] fdeep;
 23 //falen是从当前节点向FA反过去走能到的最远距离
 24     void dfs(int now,int fa,int faLen) {
 25 //找顺着走最远的子节点
 26         int fIND = -1;
 27         for (Integer i : adj.get(now)) {
 28             if (i == fa) continue;
 29             if (fIND == -1 || rdeep[i] > rdeep[fIND]) {
 30                 fIND = i;
 31             }
 32         }
 33 //找不到,当前就是叶子节点,退出
 34         if (fIND == -1) {
 35             fdeep[now] = faLen;
 36             return;
 37         }
 38 //找第二远的节点
 39         int sIND = -1;
 40         for (Integer i : adj.get(now)) {
 41             if (i == fa) continue;
 42             if (i == fIND) continue;
 43             if (sIND == -1 || rdeep[i] > rdeep[sIND]) {
 44                 sIND = i;
 45             }
 46         }
 47 //没有第二远,只能向FA反向走
 48         if (sIND == -1) {
 49             fdeep[now] = faLen;
 50             dfs(fIND,now,faLen+1);
 51             return;
 52         }
 53 //向最远的走或者向FA走哪个更远
 54         int v1 = rdeep[fIND] + 1 > faLen ? rdeep[fIND] + 1 : faLen;
 55 //向第二远的走或向FA走哪个更远
 56         int v2 = rdeep[sIND] + 1 > faLen ? rdeep[sIND] + 1 : faLen;
 57 
 58 //更新当前faLen
 59         fdeep[now] = faLen > v1? faLen : v1;
 60         fdeep[now] = fdeep[now] > v2? fdeep[now] : v2;
 61 
 62 //更新子节点
 63         for (Integer i : adj.get(now)) {
 64             if (i == fa) continue;
 65 //最远的那个子节点:沿着第二个走
 66 //其他沿着最远的走
 67             if (i == fIND) {
 68                 dfs(i,now,v2+1);
 69             } else {
 70                 dfs(i,now,v1+1);
 71             }
 72         }
 73     }
 74 
 75 
 76     void solve() throws IOException {
 77 //读入
 78         int n = Integer.parseInt(br.readLine());
 79         adj = new ArrayList< LinkedList<Integer> >();
 80         rdeep = new int[n+1];
 81         fdeep = new int[n+1];
 82         for (int i = 0; i <= n; i++) {
 83             adj.add(new LinkedList<Integer>());
 84         }
 85         for (int i = 2; i <= n; i++) {
 86             int j = Integer.parseInt(br.readLine());
 87             adj.get(i).add(j);
 88             adj.get(j).add(i);
 89         }
 90         dfs(1,0);
 91         dfs(1,0,0);
 92         Set<Integer> ans = new TreeSet<Integer>();
 93         int now = n + n;
 94 //        debug(fdeep);
 95 //        debug(rdeep);
 96 //按要求从小到大输出所有答案
 97         for (int i = 1; i <= n; i++) {
 98             int deep = fdeep[i] > rdeep[i] ? fdeep[i] : rdeep[i];
 99             if (deep < now) {
100                 now = deep;
101                 ans.clear();
102             }
103             if (deep == now) {
104                 ans.add(i);
105             }
106         }
107         for (Integer i: ans) {
108             System.out.print(i + " ");
109         }
110     }
111     void debug(Objectx) {
112         System.err.println(Arrays.deepToString(x));
113     }
114 }


posted on 2011-02-22 23:25 sweetsc 阅读(235) 评论(0)  编辑  收藏

只有注册用户登录后才能发表评论。


网站导航: