PKU : 3107 - Godfather
問題概要
http://poj.org/problem?id=3107
連結なツリー構造が与えられます.
この中のノードをひとつ消したとき, 複数のツリーに分割されます.
分割された各ツリーのノード数の最大が最小化されるようにするためには, どのノードを消せばいいでしょうか.
アルゴリズム
DFSで解けます.
DFSをしながら最小値を更新していきましょう.
この問題では, DFSが想定解法だと思われますが, PKUでは何かしら工夫しないと通らないようになっているようです.
C++でやる人はがんばってください(limitは2秒)
僕は, C++でTLEとか言われたので, Javaに逃げました(limitは10秒)
プログラム
static int n,ansMin; static ArrayList<ArrayList<Integer>> map; static ArrayList<Integer> ans; static boolean[] used; static int dfs(int id){ int res = 1; int maxCnt = 0; used[id] = true; for(int next : map.get(id)){ if(!used[next]){ int cnt = dfs(next); res += cnt; if(maxCnt < cnt) maxCnt = cnt; } } if(maxCnt < n-res) maxCnt = n - res; if(maxCnt == ansMin){ ans.add(id+1); } else if(maxCnt < ansMin){ ansMin = maxCnt; ans = new ArrayList<Integer>(); ans.add(id+1); } return res; } public static void main(String[] args)throws IOException{ BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); while(br.ready()){ n = Integer.parseInt(br.readLine()); map = new ArrayList<ArrayList<Integer>>(); for(int i=0;i<n;i++){ map.add(new ArrayList<Integer>()); } for(int i=1;i<n;i++){ String[] s = br.readLine().split(" "); int a = Integer.parseInt(s[0]) - 1; int b = Integer.parseInt(s[1]) - 1; map.get(a).add(b); map.get(b).add(a); } used = new boolean[n]; ansMin = Integer.MAX_VALUE; dfs(0); Collections.sort(ans); System.out.println(ans.toString().replaceAll("\\[|\\]|,","")); } }