PROBLEM LINK:
Author: Sandeep Singh
Tester: Arnab Chanda
Editorialist: Sandeep SIngh
DIFFICULTY:
MEDIUM
PREREQUISITES:
DFS
EXPLANATION:
Let M_u be the size of the biggest component we get on removing node u. We have to find the node removing which will give the smallest M_u. We can do this by finding an answer for each node and displaying the minimum.
Let’s assume the tree is rooted at node 1 and find the size of subtrees for each node and store it in the array sz such tat sz[u] gives the size of subtree u.
How?
This can be done with standard dfs and dp. See the solution.
Let’s focus on finding M_u for any node and then we can find the minimum amongst all M_us.
if a node is removed, the components formed will be rooted at all its children and 1 at its parent. Size of those at children is sz[child] and the size of the parent one is
N - (sum of the sizes of child subtrees). The max amongst them is our M_u.
We can calculate this for each node and find the optimal answer. Don’t forget to print the smallest node incase of multiple answers.
TIme complexity - O(N)
SOLUTIONS:
Setter's Solution
//What a drag
#include <bits/stdc++.h>
#include <assert.h>
#define ll long long
#define max(a,b) (a>b?a:b)
#define min(a,b) (a<b?a:b)
#define ln cout << '\n'
#define mod 1000000007
#define MxN 100005
#define all(x) x.begin(), x.end()
using namespace std;
vector <int> G[MxN], sz(MxN), par(MxN);
int n;
void dfs(int u, int p){
par[u] = p, sz[u] = 1;
for(int child : G[u]){
if(child != p){
dfs(child, u);
sz[u] += sz[child];
}
}
}
void solve(){
int i, j;
cin >> n;
for(i = 0; i <= n; ++i) G[i].clear();
for(i = 1; i < n; ++i){
int u, v;
cin >> u >> v;
assert(u != v);
G[u].push_back(v); G[v].push_back(u);
}
dfs(1, 0);
int mn = n, ans = 0;
for(i = 1; i <= n; ++i){
int mx = 0, total = 0;
for(int child : G[i]){
if(child == par[i]) continue;
mx = max(mx, sz[child]);
total += sz[child];
}
assert(total < n);
mx = max(mx, (n - total - 1));
if(mx < mn){
ans = i;
mn = mx;
}
}
cout << ans << " " << mn << '\n';
}
int main(){
ios_base::sync_with_stdio(false);
cin.tie(NULL);cout.tie(NULL);
#ifndef ONLINE_JUDGE
freopen("worstcase.in","r",stdin);
freopen("worstcase.out","w",stdout);
#endif
int t = 1;
cin >> t;
while(t--)
solve();
}
Tester Solution
/*
Arnab Chanda
*/
// All imports here
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.stream.Collectors;
// Template code starts here //
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public class Main {
public static void main(String[] args) {
InputStream inputStream = System.in;
OutputStream outputStream = System.out;
InputReader in = new InputReader(inputStream);
PrintWriter out = new PrintWriter(outputStream);
Debugger debug = new Debugger(out);
Objectify objectify = new Objectify(debug);
Task solver = new Task();
int test = in.nextInt();
while(test-->0){
solver.solve(1, in, out, debug, objectify);
}
out.close();
}
}
class InputReader {
public BufferedReader reader;
public StringTokenizer tokenizer;
public InputReader(InputStream stream) {
reader = new BufferedReader(new InputStreamReader(stream));
tokenizer = null;
}
public String next() {
while (tokenizer == null || !tokenizer.hasMoreTokens()) {
try {
tokenizer = new StringTokenizer(reader.readLine());
} catch (IOException e) {
throw new RuntimeException(e);
}
}
return tokenizer.nextToken();
}
public int nextInt() {
return Integer.parseInt(next());
}
public long nextLong() {
return Long.parseLong(next());
}
public Double nextDouble() {
return Double.parseDouble(next());
}
public float nextFloat() {
return Float.parseFloat(next());
}
}
class Debugger{
PrintWriter out;
Debugger(PrintWriter out){
this.out = out;
}
public <T> void printList(List<T> arrayList){
for( Object ob: arrayList){
out.print(ob+" ");
}
out.println();
}
public <T> void printSet(Set<T> set){
for(Object ob: set){
out.print(ob+" ");
}
out.println();
}
public <T> void printMap(Map<?,?> map){
for(Object ob: map.keySet()){
System.out.println(ob+" : "+map.get(ob));
}
}
}
class Objectify{
Debugger debug;
Objectify(Debugger ob){ debug = ob; }
public void printArr(int[] arr){ debug.printList(Arrays.stream(arr).boxed().collect(Collectors.toList())); }
public void printArr(double[] arr){ debug.printList(Arrays.stream(arr).boxed().collect(Collectors.toList())); }
public void printArr(long[] arr){ debug.printList(Arrays.stream(arr).boxed().collect(Collectors.toList())); }
public void printArr(char[] arr){ debug.printList( String.valueOf(arr).chars().mapToObj(c -> (char) c).collect(Collectors.toList())); }
public void printArr(String[] arr){ debug.printList(Arrays.asList(arr)); }
public void printMatrix(int[][] arr){ for(int a[]:arr) printArr(a); }
public void printMatrix(double[][] arr){ for(double a[]:arr) printArr(a); }
public void printMatrix(long[][] arr){ for(long a[]:arr) printArr(a); }
public void printMatrix(char[][] arr){ for(char a[]:arr) printArr(a); }
public void printMatrix(String[][] arr){ for(String a[]:arr) printArr(a); }
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Template code ends here
class Task {
final long MOD = (int)Math.pow(10,9)+7;
int n;
public void solve(int testNumber, InputReader sc, PrintWriter out, Debugger debug, Objectify objectify) {
// write your code here
n = sc.nextInt();
List<List<Integer>> map = new ArrayList<>();
for(int i = 0; i <= n; i++){
map.add(new ArrayList<>());
}
for(int i = 0; i < n-1; i++){
int u = sc.nextInt();
int v = sc.nextInt();
map.get(u).add(v);
map.get(v).add(u);
}
int [] ans = new int[n+1];
dfs(map, ans, 1, 0);
int X = 0;
int W = Integer.MAX_VALUE;
for(int i = n; i >= 1; i--){
if (ans[i] <= W){
W = ans[i];
X = i;
}
}
out.println(X+" "+W);
}
public int dfs(List<List<Integer>> map, int[] ans, int node, int parent){
int sum = 0;
for(int i: map.get(node)){
if (i!=parent){
int a = dfs(map, ans, i, node);
ans[node] = Math.max(ans[node], a);
sum+=a;
}
}
ans[node] = Math.max(ans[node], n - sum - 1);
return sum + 1;
}
}