1+ /*
2+ 1. 아이디어: 트리 구조 원리 사용
3+ 주어진 노드와 간선을 트리 구조로 저장하여 루트를 0으로 잡고 탐색
4+
5+ 이때 각 노드를 루트로하는 XOR연산의 합을 미리 계산
6+
7+ 이후, edges[][]를 완전탐색하여 2개의 제거할 간선을 고르고, 3개의 경우의 수를 기준으로 값을 계산
8+
9+ 2. 시간복잡도: O(E) + O(V^2) + O(E^2) => O(V^2) (V ~= E)
10+
11+ 3. 자료구조/알고리즘: DFS, Tree
12+
13+ */
14+
15+ class Solution {
16+ private List <List <Integer >> tree = new ArrayList <>();
17+ private int n ;
18+ private int [] xorSum ;
19+ private int [] depths ;
20+ private boolean [][] isAncestor ;
21+
22+ public int minimumScore (int [] nums , int [][] edges ) {
23+ // 모든 연결된 간선중 2개 제거
24+ // 가능한 모든 경우의 수 중 최소 점수
25+
26+ int ans = Integer .MAX_VALUE ;
27+ n = nums .length ;
28+ // 각 노드 기준 모든 서브트리의 xor값
29+ xorSum = new int [n ];
30+ // 루트 기준 떨어진 길이
31+ depths = new int [n ];
32+ // 조상 여부
33+ isAncestor = new boolean [n ][n ];
34+
35+ for (int i =0 ; i <n ; i ++) {
36+ tree .add (new ArrayList <>());
37+ }
38+ for (int [] edge : edges ) {
39+ int a = edge [0 ];
40+ int b = edge [1 ];
41+
42+ tree .get (a ).add (b );
43+ tree .get (b ).add (a );
44+ }
45+
46+ // 각 노드기준 모든 xor연산 합 계산
47+ dfs (0 , -1 , nums , 0 );
48+
49+ for (int i =0 ; i <edges .length -1 ; i ++) {
50+ for (int j =i +1 ; j <edges .length ; j ++) {
51+ int [] edge1 = edges [i ];
52+ int [] edge2 = edges [j ];
53+
54+ int child1 = depths [edge1 [0 ]] > depths [edge1 [1 ]] ? edge1 [0 ] : edge1 [1 ];
55+ int child2 = depths [edge2 [0 ]] > depths [edge2 [1 ]] ? edge2 [0 ] : edge2 [1 ];
56+
57+ int a = xorSum [child1 ];
58+ int b = xorSum [child2 ];
59+ int c = xorSum [0 ];
60+
61+ if (isAncestor [child1 ][child2 ]) {
62+ //xorSum[child2]
63+ //xorSum[child1]^xorSum[child2]
64+ //xorSum[0]^xorSum[child1]
65+
66+ a ^= xorSum [child2 ];
67+ c ^= xorSum [child1 ];
68+ }
69+ else if (isAncestor [child2 ][child1 ]) {
70+ //xorSum[child1]
71+ //xorSum[child2]^xorSum[child1]
72+ //xorSum[0]^xorSum[child2]
73+
74+ b ^= xorSum [child1 ];
75+ c ^= xorSum [child2 ];
76+ }
77+ else {
78+ //xorSum[child1]
79+ //xorSum[child2]
80+ //xorSum[0]^xorSum[child1]^xorSum[child2]
81+
82+ c = c ^a ^b ;
83+ }
84+
85+ ans = Math .min (ans , Math .max (a ,Math .max (b ,c )) - Math .min (a ,Math .min (b ,c )));
86+ if (ans == 0 ) return 0 ;
87+ }
88+ }
89+
90+ return ans ;
91+ }
92+
93+ private int dfs (int curr , int parent , int []nums , int depth ) {
94+ int currXor = nums [curr ];
95+ depths [curr ] = depth ;
96+
97+ for (int next : tree .get (curr )) {
98+ if (next == parent ) continue ;
99+
100+ for (int i = 0 ; i < n ; i ++) {
101+ if (isAncestor [i ][curr ]) isAncestor [i ][next ] = true ;
102+ }
103+ isAncestor [curr ][next ] = true ;
104+ currXor ^= dfs (next , curr , nums , depth +1 );
105+ }
106+
107+ xorSum [curr ] = currXor ;
108+ return currXor ;
109+ }
110+ }
0 commit comments