小红书4.9笔试
1题选手,太菜了受不了了
1.平衡,给出一个树,删除任意一条边,求删除后两个树的节点之差的绝对值最小值,并且求方案数目
输入:
第一行 节点数目n
第二行连续n-1行,输入两个数,表示两个节点有1条边
输出
最小值 空格 方案数
思路:
一次遍历记录子树节点数目在subtrees。
一次遍历在遍历子节点的时候 算出删除父子节点边后的 两个树的节点数目之差,借助subtrees,同时得到最小值。
一次遍历 同上次遍历,但是是判断节点数目之差等于最小值的情况数目。
import java.util.*; public class Main { static int n; static int mins=Integer.MAX_VALUE; static int[] subtrees; static boolean[] visit; static boolean[] visit2; static boolean[] visit3; static ArrayList<Integer>[] res; static int result=0; public static int dfs1(int i){ visit[i] = true; int subcount=1; for(int j=0;j<res[i].size();j++){ int next = res[i].get(j); if(!visit[next]){ subcount += dfs1(next); } } subtrees[i]=subcount; return subcount; } public static void dfs2(int i){ visit2[i]=true; for(int j=0;j<res[i].size();j++){ int next = res[i].get(j); int ret = subtrees[next]; int ret2 = n-ret; int chec = Math.abs(ret2-ret); if(mins>chec)mins=chec; if(!visit2[next]){ dfs2(next); } } } public static void dfs3(int i){ visit3[i] = true; for(int j=0;j<res[i].size();j++){ int next = res[i].get(j); if(!visit3[next]){ int ret = subtrees[next]; int ret2 = n-ret; int chec = Math.abs(ret2-ret); if(mins==chec)result++; dfs3(next); } } } public static void main(String[] args) { Scanner sc = new Scanner(System.in); n = sc.nextInt(); res = new ArrayList[n+5]; visit = new boolean[n+5]; visit2 = new boolean[n+5]; visit3 = new boolean[n+5]; subtrees = new int[n+5]; for(int i=0;i<n+5;i++){ res[i] = new ArrayList<Integer>(); } for(int i=0;i<n-1;i++){ int v = sc.nextInt(); int u = sc.nextInt(); res[v].add(u); res[u].add(v); } dfs1(1); dfs2(1); dfs3(1); System.out.print(mins); System.out.print(" "); System.out.println(result); } }#我的实习求职记录##小红书信息集散地##小红书24届实习招聘#