蓝桥杯2015年JavaB组

三角形面积

答案为28

立方自变身

答案为6

package Contest_2015;
/**
 * 答案为6
 * @author Admin
 *
 */
public class 立方变身 {

	public static void main(String[] args) {
		long count = 0;
		for (int i = 1; i <= 50000; i++) {
			long num = (long) Math.pow(i, 3);
			long temp = function(num);
			if(temp == i){
				count++;
				System.out.println(i);
			}
			
		}
		System.out.println(count+"个");
	}
	
	// 按位累加
	private static long function(long num){
		int sum = 0;
		while(num!=0){
			sum += num%10;
			num/=10;
		}
		return sum;
	}

}

三羊献瑞(DFS全排列)

DFS全排列,答案为1085

package Contest_2015;

/**
 * abcd+efgb=efcbh
 * 
 * @author Admin
 *
 */
public class 三羊献瑞 {
	static int[] visit;
	static int[] comb;

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		visit = new int[10];
		comb = new int[8];
		dfs(0);
	}

	private static void dfs(int depth) {
		if (depth == 8) {
			if (check()) {
				if(comb[4] == 0)
					return;
				System.out.printf("%d%d%d%d\n", comb[4], comb[5], comb[6], comb[1]);
//				for (int i = 0; i < comb.length; i++) {
//					System.out.println(comb[i]);
//				}
			}
			return;
		}

		for (int i = 0; i <= 9; i++) {
			if (visit[i] == 0) {
				comb[depth] = i;
				visit[i] = 1;
				dfs(depth + 1);
				visit[i] = 0;// go back
			}
		}
	}

	// abcd+efgb=efcbh
	private static boolean check() {
		int a = comb[0];
		int b = comb[1];
		int c = comb[2];
		int d = comb[3];
		int e = comb[4];
		int f = comb[5];
		int g = comb[6];
		int h = comb[7];

		int abcd = a * 1000 + b * 100 + c * 10 + d;
		int efgb = e * 1000 + f * 100 + g * 10 + b;
		int efcbh = e * 10000 + f * 1000 + c * 100 + b * 10 + h;
		if (abcd + efgb == efcbh)
			return true;
		return false;
	}

}

循环节长度

package Contest_2015;

import java.util.Vector;

public class 循环节长度 {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		System.out.println(f(13, 11));
	}

	public static int f(int n, int m) {
		n = n % m;
		Vector v = new Vector();

		for (;;) {
			v.add(n);
			n *= 10;
			n = n % m;
			if (n == 0)
				return 0;
			if (v.indexOf(n) >= 0)
				return v.size(); // 填空
		}
	}
}

九数组分数(DFS全排列)

DFS全排列,填空部分为“回溯”操作

package Contest_2015;

public class 九数组分数 {

	public static void test(int[] x) {
		int a = x[0] * 1000 + x[1] * 100 + x[2] * 10 + x[3];
		int b = x[4] * 10000 + x[5] * 1000 + x[6] * 100 + x[7] * 10 + x[8];
		if (a * 3 == b) 
			System.out.println(a + " " + b);
	}

	// 全排列
	public static void f(int[] x, int k) {
		if (k >= x.length) {
			test(x);
			return;
		}

		for (int i = k; i < x.length; i++) {
			{
				int t = x[k];
				x[k] = x[i];
				x[i] = t;
			}
			f(x, k + 1);
			{
				int t = x[k];
				x[k] = x[i];
				x[i] = t;
			} // 填空
		}
	}

	public static void main(String[] args) {
		int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
		f(x, 0);
	}
}

牌型种数(DFS+剪枝)

package Contest_2015;

/**
 * 
 * 牌型种数
 * 
 * 小明被劫持到X赌城,被迫与其他3人玩牌。 一副扑克牌(去掉大小王牌,共52张),均匀发给4个人,每个人13张。 这时,小明脑子里突然冒出一个问题:
 * 如果不考虑花色,只考虑点数,也不考虑自己得到的牌的先后顺序,自己手里能拿到的初始牌型组合一共有多少种呢?
 * 
 * 请填写该整数,不要填写任何多余的内容或说明文字。
 * 
 * @author Admin
 *
 */
public class 牌型种数 {
	static int count = 0;

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		dfs(0, 0);
		System.out.println(count);
	}

	// 对每种类型的牌的数量进行枚举,统计最终符合条件的情况
	private static void dfs(int depth, int sum) {
		if (depth == 13) {
			if (sum == 13)
				count++;
			return;
		}

		if (sum > 13)// 剪枝
			return;

		for (int i = 0; i <= 4; i++) {
			dfs(depth + 1, sum + i);
		}
	}

}

加法变乘法

模拟一下,答案为16。

package Contest_2015;

/**
 * 
 * 加法变乘法
 * 
 * 我们都知道:1+2+3+ ... + 49 = 1225 现在要求你把其中两个不相邻的加号变成乘号,使得结果为2015
 * 
 * 比如: 1+2+3+...+10*11+12+...+27*28+29+...+49 = 2015 就是符合要求的答案。
 * 
 * 请你寻找另外一个可能的答案,并把位置靠前的那个乘号左边的数字提交(对于示例,就是提交10)。
 * 
 * 注意:需要你提交的是一个整数,不要填写任何多余的内容。
 * 
 * 答案为16
 * 
 * @author Admin
 *
 */
public class 加法变乘法 {

	public static void main(String[] args) {
		int[] data = new int[50];
		for (int i = 1; i < data.length; i++) {
			data[i] = i;
		}
		// 暴力,枚举做乘法的位置
		for (int i = 1; i < data.length - 1; i++) {
			for (int j = i + 2; j < data.length - 1; j++) {
				function(i, j, data);// 计算,并对符合条件的情况进行输出
			}
		}
	}

	// 计算data[1]+data[2]+...+data[index1]*data[index1+1]+...+data[index2]*data[index2+1]+...
	private static void function(int index1, int index2, int[] data) {
		int sum = data[index1] * data[index1 + 1] + data[index2] * data[index2 + 1];
		int[] visit = new int[50];
		visit[index1] = 1;
		visit[index1 + 1] = 1;
		visit[index2] = 1;
		visit[index2 + 1] = 1;
		for (int i = 1; i < data.length; i++) {
			if (visit[i] == 0)
				sum += data[i];
		}
		if (sum == 2015)
			System.out.printf("%d*%d  %d*%d\n", index1, index1 + 1, index2, index2 + 1);
	}

}

饮料换购

白给题

package Contest_2015;

import java.util.Scanner;

/**
 * 
 * 饮料换购
 * 
 * 乐羊羊饮料厂正在举办一次促销优惠活动。乐羊羊C型饮料,凭3个瓶盖可以再换一瓶C型饮料,并且可以一直循环下去,但不允许赊账。
 * 
 * 请你计算一下,如果小明不浪费瓶盖,尽量地参加活动,那么,对于他初始买入的n瓶饮料,最后他一共能得到多少瓶饮料。
 * 
 * 输入:一个整数n,表示开始购买的饮料数量(0<n<10000) 输出:一个整数,表示实际得到的饮料数
 * 
 * 例如: 用户输入: 100 程序应该输出: 149
 * 
 * 用户输入: 101 程序应该输出: 151
 * 
 * @author Admin
 *
 */
public class 饮料换购 {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Scanner sc = new Scanner(System.in);
		int n = sc.nextInt();
		int count = n;
		while (n >= 3) {
			n -= 3;
			n++;
			count++;
		}
		System.out.println(count);
	}

}

垒骰子(DFS)

package Contest_2015;

import java.util.Scanner;

public class 垒骰子 {

	static long count = 0;

	static boolean[][] martix;

	private static int getOp(int n) {
		if (n == 1)
			return 4;
		if (n == 4)
			return 1;
		if (n == 2)
			return 5;
		if (n == 5)
			return 2;
		if (n == 3)
			return 6;
		if (n == 6)
			return 3;
		return -1;
	}

	// 根据curHead确定nextBottom,并试探剩下的骰子
	// nextHead
	// nextBottom
	// =======
	// curHead
	// curBottom
	private static void dfs(int curHead, int height, int key) {
		if (height == key) {
			count++;
			count %= 1000000000 + 7;
			return;
		}

		// 选择nextBottom
		for (int i = 1; i < 7; i++) {
			// 排斥则跳过
			if (martix[i][curHead]) {
				continue;
			}
			int nextHead = getOp(i);
			dfs(nextHead, height + 1, key);
		}
	}

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Scanner sc = new Scanner(System.in);
		while (sc.hasNext()) {
			int n = sc.nextInt();// n个骰子
			int m = sc.nextInt();
			martix = new boolean[7][7];
			for (int i = 0; i < m; i++) {
				int x = sc.nextInt();
				int y = sc.nextInt();
				martix[x][y] = true;
				martix[y][x] = true;
			}
			long begin = System.currentTimeMillis();
			for (int i = 1; i < 7; i++) {
				dfs(i, 1, n);// 初始1层
			}
			long end = System.currentTimeMillis();
			// 骰子的四个面
			long ans = count * (long) Math.pow(4, n) % (1000000000 + 7);
			System.out.println(ans);
			System.out.println(end - begin);
		}
	}

}

垒筛子(记忆化DFS)

记忆化搜索至少可以过60%的数据

package Contest_2015;

import java.util.Scanner;

public class 垒骰子_记忆化搜索 {

	static int n;
	static long[][] record;
	static boolean[][] martix;

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		init();
		long ans = 0;
		for (int i = 1; i < 7; i++) {
			ans += dfs(i, 1);// 初始1层
		}
		// 骰子的四个面
		ans = (ans % (1000000000 + 7)) * pow(4, n) % (1000000000 + 7);
		System.out.println(ans);
	}

	private static long pow(int a, int b) {
		long ans = 1;
		for (int i = 0; i < b; i++) {
			ans *= a;
			ans %= (1000000000 + 7);
		}
		return ans;
	}

	private static int getOp(int n) {
		if (n == 1)
			return 4;
		if (n == 4)
			return 1;
		if (n == 2)
			return 5;
		if (n == 5)
			return 2;
		if (n == 3)
			return 6;
		if (n == 6)
			return 3;
		return -1;
	}

	// 根据curHead确定nextBottom,并试探剩下的骰子
	// nextHead
	// nextBottom
	// =======
	// curHead
	// curBottom
	private static long dfs(int curHead, int height) {
		if (record[curHead][height] != -1) {// 已计算过
			return record[curHead][height];
		}

		if (height == n) {
			record[curHead][height] = 1;
			return record[curHead][height];
		}

		long temp = 0;
		// 选择nextBottom
		for (int i = 1; i < 7; i++) {
			// 排斥则跳过
			if (martix[i][curHead]) {
				continue;
			}
			int nextHead = getOp(i);
			temp += dfs(nextHead, height + 1);
		}
		record[curHead][height] = temp % (1000000000 + 7);
		return record[curHead][height];
	}

	private static void init() {
		Scanner sc = new Scanner(System.in);
		n = sc.nextInt();// n个骰子
		int m = sc.nextInt();
		martix = new boolean[7][7];
		for (int i = 0; i < m; i++) {
			int x = sc.nextInt();
			int y = sc.nextInt();
			martix[x][y] = true;
			martix[y][x] = true;
		}
		record = new long[7][n + 1];
		for (int i = 1; i < record.length; i++) {
			for (int j = 1; j < record[i].length; j++) {
				record[i][j] = -1;
			}
		}
	}

}

垒筛子(动态规划)

package Contest_2015;

import java.util.Scanner;

public class 垒骰子_动态规划 {
	static int n;
	static long[][] dp;
	static boolean[][] martix;

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		init();
		for (int i = 2; i < dp.length; i++) {
			for (int j = 1; j <= 6; j++) {
				function(i, j);// 更新dp[i][j]
			}
		}
		long sum = 0;
		for (int i = 1; i <= 6; i++) {
			sum += dp[n][i];
		}
		sum = (sum % (1000000000 + 7)) * pow(4, n) % (1000000000 + 7);
		System.out.println(sum);
	}

	private static long pow(int a, int b) {
		long ans = 1;
		for (int i = 0; i < b; i++) {
			ans *= a;
			ans %= (1000000000 + 7);
		}
		return ans;
	}

	private static void function(int row, int col) {
		for (int k = 1; k <= 6; k++) {
			if (martix[col][getOp(k)] == true)// 排斥
				continue;

			dp[row][col] += dp[row - 1][k];
			dp[row][col] %= (1000000000 + 7);
		}
	}

	private static int getOp(int n) {
		if (n == 1)
			return 4;
		if (n == 4)
			return 1;
		if (n == 2)
			return 5;
		if (n == 5)
			return 2;
		if (n == 3)
			return 6;
		if (n == 6)
			return 3;
		return -1;
	}

	private static void init() {
		Scanner sc = new Scanner(System.in);
		n = sc.nextInt();// n个骰子
		int m = sc.nextInt();
		martix = new boolean[7][7];
		for (int i = 0; i < m; i++) {
			int x = sc.nextInt();
			int y = sc.nextInt();
			martix[x][y] = true;
			martix[y][x] = true;
		}
		dp = new long[n + 1][7];
		for (int i = 1; i <= 6; i++) {
			dp[1][i] = 1;
		}
	}
}

垒筛子(DP滚动数组+快速幂)

面对100%的数据规模依旧超时

package Contest_2015;

import java.util.Scanner;

public class 垒筛子_动态规划_滚动数组 {
	static int n;
	static long[][] dp;
	static boolean[][] martix;

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		init();
		int T = n - 1;
		int e = 0;
		while (T-- != 0) {// 循环T次
			e ^= 1;// 滚动(e.g. 10^00 = 10)
			for (int j = 1; j <= 6; j++) {
				function(e, j);// 更新dp[x][y]
			}
		}
		long sum = 0;
		for (int i = 1; i <= 6; i++) {
			sum += dp[e][i];
		}
		sum %= (1000000000 + 7);
		sum = (sum * quickPow(4, n)) % (1000000000 + 7);
		System.out.println(sum);
	}

	// 快速幂,含取模。
	private static long quickPow(int a, int b) {
		if (b == 1)
			return a;

		long temp = quickPow(a, b / 2);
		temp = temp * temp % (1000000000 + 7);
		return (b % 2 == 0 ? 1 : a) * temp % (1000000000 + 7);
	}

	private static void function(int row, int col) {
		long sum = 0;
		for (int k = 1; k <= 6; k++) {
			if (martix[col][getOp(k)] == true)// 排斥
				continue;

			sum += dp[row ^ 1][k];
			sum %= (1000000000 + 7);
		}
		dp[row][col] = sum;
	}

	private static int getOp(int n) {
		if (n == 1)
			return 4;
		if (n == 4)
			return 1;
		if (n == 2)
			return 5;
		if (n == 5)
			return 2;
		if (n == 3)
			return 6;
		if (n == 6)
			return 3;
		return -1;
	}

	private static void init() {
		Scanner sc = new Scanner(System.in);
		n = sc.nextInt();// n个骰子
		int m = sc.nextInt();
		martix = new boolean[7][7];
		for (int i = 0; i < m; i++) {
			int x = sc.nextInt();
			int y = sc.nextInt();
			martix[x][y] = true;
			martix[y][x] = true;
		}
		dp = new long[2][7];
		for (int i = 1; i <= 6; i++) {
			dp[0][i] = 1;
		}
	}
}

垒筛子(矩阵快速幂)

可以通过100%数据

package Contest_2015;

import java.util.Scanner;

public class 垒筛子_矩阵快速幂 {
	static int n;
	static long[][] martix;
	static long[][] a;
	static final int MOD = 1000000000 + 7;
	static int op[] = { 0, 4, 5, 6, 1, 2, 3 };

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		init();
		// 计算T^n-1
		martix = quickMartix(martix, n - 1);
		long sum = 0;
		for (int i = 1; i <= 6; i++) {
			for (int j = 1; j <= 6; j++) {
				sum = (sum + martix[i][j]) % MOD;
			}
		}
		sum %= MOD;
		sum = (sum * quickPow(4, n)) % MOD;
		System.out.println(sum);
	}

	// 6x6矩阵相乘
	private static long[][] mulMartix(long[][] x, long[][] y) {
		long[][] ans = new long[7][7];
		for (int i = 1; i < x.length; i++) {// 遍历行
			for (int j = 1; j < y[0].length; j++) {// 遍历列
				for (int k = 1; k < y.length; k++) {// 遍历列中的每一个元素
					ans[i][j] = (ans[i][j] + x[i][k] * y[k][j]) % MOD;
				}
			}
		}
		return ans;
	}

	// 矩阵快速幂
	private static long[][] quickMartix(long[][] martix, int n) {
		long[][] ans = new long[7][7];
		for (int i = 1; i <= 6; i++)
			ans[i][i] = 1;
		while (n > 0) {
			if (n % 2 != 0)
				ans = mulMartix(ans, martix);
			martix = mulMartix(martix, martix);
			n /= 2;
		}
		return ans;
	}

	// 整数快速幂,含取模。
	private static long quickPow(int a, int b) {
		if (b == 1)
			return a;

		long temp = quickPow(a, b / 2);
		temp = temp * temp % (1000000000 + 7);
		return (b % 2 == 0 ? 1 : a) * temp % (1000000000 + 7);
	}

	private static void init() {
		Scanner sc = new Scanner(System.in);
		n = sc.nextInt();// n个骰子
		int m = sc.nextInt();
		martix = new long[7][7];
		for (int i = 1; i < martix.length; i++) {
			for (int j = 1; j < martix[i].length; j++) {
				martix[i][j] = 1;
			}
		}
		for (int i = 0; i < m; i++) {
			int x = sc.nextInt();
			int y = sc.nextInt();
			martix[x][op[y]] = 0;
			martix[y][op[x]] = 0;
		}
		a = new long[7][2];
		for (int i = 1; i <= 6; i++) {
			a[i][1] = 1;
		}
	}
}

生命之树(暴力过部分数据)

当成子集问题,暴力可以过一部分的数据。

package Contest_2015;

import java.util.Scanner;

public class 生命之树_暴力 {
	static int n;
	static int[] val;
	static int[] mark;
	static int[][] g;
	static int max = -1;

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		init();
		function(1);
		System.out.println(max);
	}

	// 枚举所有节点选与不选的情况
	private static void function(int index) {
		if (index == n + 1) {
			int sum = cal();
			if (sum > max)
				max = sum;
			return;
		}

		// 不选
		function(index + 1);
		// 选
		// 检查能否选,等价于已选择的节点中,是否与当前待选择的节点连通
		if (isOk(index)) {
			mark[index] = 1;
			mark[0]++;
			function(index + 1);
			mark[index] = 0;
			mark[0]--;
		}
	}

	// 检查能否选,等价于已选择的节点中,是否与当前待选择的节点连通
	private static boolean isOk(int index) {
		if (mark[0] == 0)// 代表一个节点都没有
			return true;

		for (int i = 1; i < g[index].length; i++) {
			if (g[index][i] == 1 && mark[i] == 1)
				return true;
		}
		return false;
	}

	private static int cal() {
		int sum = 0;
		for (int i = 1; i < mark.length; i++) {
			if (mark[i] == 1)
				sum += val[i];
		}
		return sum;
	}

	private static void init() {
		Scanner sc = new Scanner(System.in);
		n = sc.nextInt();
		val = new int[n + 1];
		mark = new int[n + 1];
		g = new int[n + 1][n + 1];
		for (int i = 1; i < val.length; i++) {
			val[i] = sc.nextInt();
		}
		for (int i = 0; i < n - 1; i++) {
			int vertex1 = sc.nextInt();
			int vertex2 = sc.nextInt();
			g[vertex1][vertex2] = 1;
			g[vertex2][vertex1] = 1;
		}
	}

}

生命之树(搜索)

只能过部分数据

package Contest_2015;

import java.util.Scanner;

/**
 * 普通DFS搜索
 * 
 * @author Admin
 *
 */
public class 生命之树_搜索 {
	static int n;
	static int[] val;
	static int[] mark;
	static int[][] g;

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		init();
		int max = val[1];
		// O(n^2)时间复杂度,可以改为记忆化搜索
		for (int i = 1; i <= n; i++) {
			int temp = dfs(i);
			if (temp > max)
				max = temp;
		}
		System.out.println(max);
	}

	// 计算以root为根的子树权值之和的最大值(即不添加权值为负的子节点)
	private static int dfs(int root) {
		if (isEnd(root)) {// 所有邻接节点已访问
			return val[root];
		}

		mark[root] = 1;// 标记已访问
		int sum = val[root];
		for (int i = 1; i <= n; i++) {// 访问邻接节点
			if (g[root][i] == 1 && mark[i] == 0) {
				int temp = dfs(i);
				if (temp >= 0)// 只累加正权值的邻接节点
					sum += temp;
			}
		}
		return sum;
	}

	private static boolean isEnd(int root) {
		for (int i = 1; i < n; i++) {
			if (g[root][i] == 1 && mark[i] == 0)
				return false;
		}
		return true;
	}

	private static void init() {
		Scanner sc = new Scanner(System.in);
		n = sc.nextInt();
		val = new int[n + 1];
		mark = new int[n + 1];
		g = new int[n + 1][n + 1];
		for (int i = 1; i <= n; i++) {
			val[i] = sc.nextInt();
		}
		for (int i = 0; i < n - 1; i++) {
			int vertex1 = sc.nextInt();
			int vertex2 = sc.nextInt();
			g[vertex1][vertex2] = 1;
			g[vertex2][vertex1] = 1;
		}
	}
}

生命之树(树形DP-Java)

由普通搜索改进得来,邻接矩阵存图爆内存,所以选择邻接链表存图。
但由于Java消耗高,所以在OJ上还是过不了。

import java.util.ArrayList;
import java.util.Scanner;

/**
 * 由普通DFS搜索-->记忆化搜索-->树形DP逐步改进
 * 
 * @author Admin 5 0 -2 -3 -4 -5 4 2 3 1 1 2 2 5
 *
 */
public class Main {
	static int n;
	static long max;
	static int[] val;
	static long[] dp;// mark[i]表示以i为根的最大权值和子树的权值和
	static int[] mark;
	static ArrayList<Integer>[] g;

	public static void main(String[] args) {
		init();
		dfs(1);// 线性时间复杂度
		System.out.println(max);
	}

	// 树形DP,自底向上
	// 计算以root为根的子树权值之和的最大值(即不添加权值为负的子节点),并保存记录
	private static void dfs(int root) {
		if (isEnd(root)) {// 所有邻接节点已访问
			mark[root] = 1;
			dp[root] = val[root];
			if (dp[root] > max)
				max = dp[root];
			return;
		}

		mark[root] = 1;// 标记已访问
		long sum = val[root];
		for (int index = 0; index < g[root].size(); index++) {// 访问邻接节点
			int vertex = g[root].get(index);
			if (mark[vertex] == 0) {
				dfs(vertex);
				if (dp[vertex] >= 0)// 只累加正权值的邻接节点
					sum += dp[vertex];
			}
		}
		dp[root] = sum;// 保存计算结果
		if (dp[root] > max)
			max = dp[root];
	}

	private static boolean isEnd(int root) {
		if (g[root].size() == 0)
			return true;
		int lastVertex = g[root].get(g[root].size() - 1);
		if (mark[lastVertex] == 0)
			return false;
		return true;
	}

	private static void init() {
		Scanner sc = new Scanner(System.in);
		n = sc.nextInt();
		val = new int[n + 1];
		dp = new long[n + 1];
		mark = new int[n + 1];
		g = new ArrayList[n + 1];
		for (int i = 1; i < g.length; i++) {
			g[i] = new ArrayList<Integer>();
		}
		for (int i = 1; i <= n; i++) {
			val[i] = sc.nextInt();
		}
		for (int i = 0; i < n - 1; i++) {
			int vertex1 = sc.nextInt();
			int vertex2 = sc.nextInt();
			g[vertex1].add(vertex2);
			g[vertex2].add(vertex1);
		}
		max = val[1];
	}
}

生命之树(树形DP-C++)

用C++重写了一遍上面的代码

#include<iostream>
#include<vector>
#include<cstring>
using namespace std;

int n;
long ans;
int val[100000 + 5];
int mark[100000 + 5];
long dp[100000 + 5];
vector<int> g[100000 + 5];

void dfs(int root) {
	mark[root] = 1;
	long sum = val[root];
	for (int index = 0; index < g[root].size(); index++)
	{
		int vertex = g[root][index];
		if (mark[vertex] == 0) {
			dfs(vertex);
			if (dp[vertex] >= 0)
				sum += dp[vertex];
		}
	}
	dp[root] = sum;
	if (dp[root] > ans)
		ans = dp[root];
}

int main() {
	memset(mark, 0, sizeof(mark));
	memset(dp, 0, sizeof(dp));
	cin >> n;
	for (int i = 1; i <= n; i++)
	{
		cin >> val[i];
	}
	for (int i = 0; i < n-1; i++)
	{
		int vertex1, vertex2;
		cin >> vertex1 >> vertex2;
		g[vertex1].push_back(vertex2);
		g[vertex2].push_back(vertex1);
	}
	ans = val[1];
	dfs(1);
	cout << ans << endl;
	return 0;
}
  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值