一道不错的记忆化搜索题目!
在建图上需要动一点点小手脚,也是很简单的思维题!
最大连通分量:
本题卡了
本题其实很简单(
建图
只需要在建图的时候,保留从电容大的节点流向电容小的节点的边(这里需要仔细理解喔!),其余边都不需要保留,接下来就是求最大连通分量啦!
动态规划
状态定义:
状态转移方程:
在这里,有可能重复计算了某个节点的分量数,因此我们使用记忆化搜索剪枝。
搜索代码
int dfs(int u) {
	if (dp[u]) return dp[u];
	dp[u] = 1;
	for (int i = h[u]; ~i; i = ne[i]) {
		int j = e[i];
		dp[u] += dfs(j);
	}
	return dp[u];
}时间复杂度
完整代码
码风比较差,请见谅
#include<ios>
#include<iomanip>
#include<iostream>
#include<cstdio>
#include<fstream>
#include<algorithm>
#include<deque>
#include<vector>
#include<list>
#include<forward_list>
#include<string>
#include<cstring>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<unordered_map>
#include<unordered_set>
#include<algorithm>
#include<functional>
#include<cstdlib>
#include<cmath>
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int, int> PII;
#define int long long
#define endl '\n'
#define IOS ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr)
#define _rep(i, a, b) for (int i = (a); i <= (b); ++i)
#define _per(i, a, b) for (int i = (b); i >= (a); --i)
#define debug(a) cout << #a << " = " << a << endl
#define PI acos(-1)
#define lowbit(x) (x&-x)
const int mod = 1e9 + 7;
const int INF = 0x3f3f3f3f;
const double EPS = 1e-8;
const int dx[4] = { -1, 0, 1, 0 };
const int dy[4] = { 0, -1, 0, 1 };
int gcd(int a, int b) { return b ? gcd(b, a % b) : a; }
int lcm(int a, int b) { return a * b / gcd(a, b); }
inline int read() {
	int x = 0, w = 1;
	char ch = getchar();
	while (ch < '0' || ch > '9') { if (ch == '-') w = -1, ch = getchar(); }
	while (ch >= '0' && ch <= '9') { x = x * 10 + (ch - '0'), ch = getchar(); }
	return x * w;
}
inline void write(int x) {
	static int sta[35];
	int top = 0;
	do {
		sta[top++] = x % 10, x /= 10;
	} while (x);
	while (top) putchar(sta[--top] + 48);  // 48 是 '0'
}
const int N = 2e5 + 10;
int T, n, c[N], dp[N], cases;
int h[N], e[N], ne[N], idx;
int son[N];
void add(int a, int b) {
	e[idx] = b, ne[idx] = h[a], h[a] = idx++;
}
int dfs(int u) {
	if (dp[u]) return dp[u];
	dp[u] = 1;
	for (int i = h[u]; ~i; i = ne[i]) {
		int j = e[i];
		dp[u] += dfs(j);
	}
	return dp[u];
}
void solve(void) {
	cin >> n;
	idx = 0;
	memset(h, -1, sizeof h);
	memset(dp, 0, sizeof dp);
	memset(son, 0, sizeof son);
	for (int i = 1; i <= n; i++) {
		cin >> c[i];
	}
	for (int i = 1; i < n; i++) {
		int u, v;
		cin >> u >> v;
		if (c[u] > c[v]) {
			add(u, v);
			son[v] = 1;
		}
		else if (c[u] < c[v]) {
			add(v, u);
			son[u] = 1;
		}
	}
	int ans = 0;
	for (int i = 1; i <= n; i++) {
		if (!son[i]) {
			ans = max(ans, dfs(i));
		}
	}
	cout << "Case #" << ++cases << ": ";
	cout << ans << endl;
}
signed main(void) {
	IOS;
	T = 1;
	// T = read();
	cin >> T;
	while (T--) {
		solve();
	}
	return 0;
}