题目
某城市有 N 个电力节点,编号 1∼N。
这些电力节点形成的电力网络,可以看作一个 N 个节点 N−1 条边的连通图。
每个电力节点都有一个固定的电容,其中第 i 个节点的电容为 Ai。
现在,可以选择其中一个节点进行供电,其它节点也可以根据实际连接以及具体电容情况接收电力。
具体来说,如果第 i 个节点通电,那么它也可以将电力传输给其它所有与它直接连接且电容严格小于 Ai 的节点。
我们希望通过合理选择初始供电节点,从而使得尽可能多的节点能够通电。
请你计算并输出可以通电的最大节点数量。
输入格式
第一行包含整数 T,表示共有 T 组测试数据。
每组数据第一行包含整数 N。
第二行包含 N 个整数 A1,A2,…,AN。
接下来 N−1 行,每行包含两个整数 Xi,Yi,表示节点 Xi 和 Yi 之间存在直接连接。
输出格式
每组数据输出一个结果,每个结果占一行。
结果表示为 Case #x: y,其中 x 为组别编号(从 1 开始),y 为可以通电的最大节点数量。
数据范围
1≤T≤100,
1≤Ai≤109,
1≤Xi,Yi≤N,
一个测试点内最多 15 组数据满足 1≤N≤2×105,其余数据满足 1≤N≤103。
- 输入样例:
2
5
1 2 3 4 3
1 3
2 3
4 3
4 5
6
1 2 3 3 1 4
3 1
3 2
3 4
4 5
1 6
- 输出样例:
Case #1: 5
Case #2: 3
样例解释
在 Case 1 中,最佳方案是给第 4 个节点供电,这样可以将电力传输到所有节点。
注意,如果给第 3 个节点供电,则电力只会传输至第 1,2 个节点,而无法传输至第 4 个节点,这样只有三个节点可以通电。
在 Case 2 中,最佳方案是给第 3 个节点供电,这样可以将电力传输至第 1,2 个节点,但是无法传输至第 4 个节点,因为 A4 并不严格小于 A3。
注意,如果给第 6 个节点供电,则电力只会传输至第 1 个节点,如果给第 4 个节点供电,则电力只会传输至第 5 个节点。
题解(代码来自https://www.acwing.com/activity/content/code/content/6570336/)
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.StreamTokenizer;
import java.util.Arrays;
public class Main {
static int N = (int) 2e5 + 10, M = 2 * N;
static int[] w = new int[N];
static int[] h = new int[N], e = new int[M], ne = new int[M];
static int idx, n;
static int[] f = new int[N];
static void add(int a, int b) {
e[idx] = b;
ne[idx] = h[a];
h[a] = idx++;
}
static StreamTokenizer st=new StreamTokenizer(
new BufferedReader(new InputStreamReader(System.in)));
static int nextInt() throws Exception{
st.nextToken();
return (int)st.nval;
}
static int dfs(int u) {
if(f[u]!=0)return f[u];
f[u]=1;
for(int i=h[u];i!=-1;i=ne[i]) {
int j=e[i];
if(f[j]==0)dfs(j);
f[u]+=f[j];
}
return f[u];
}
public static void main(String[] args) throws Exception{
int t=nextInt();
for(int i=1;i<=t;i++) {
n=nextInt();
idx=0;
Arrays.fill(h, -1);
Arrays.fill(f, 0);
for(int j=1;j<=n;j++)w[j]=nextInt();
for(int j=1;j<n;j++) {
int u=nextInt();int v=nextInt();
if(w[u]>w[v])add(u, v);
else if(w[u]<w[v])add(v, u);
}
int res=0;
for(int j=1;j<=n;j++) {
if(f[j]==0)dfs(j);
res=Math.max(res, f[j]);
if(res==n)break;
}
System.out.printf("Case #%d: %d\n",i,res);
}
}
}
思路
这道题综合运用了静态链表以及动态规划的知识。 这道题的重点在于先分析题目,这道题是一个N个点N-1条边的连通图,说明该图是一棵树,则选择使用动态规划。
则满足条件的加边
最后遍历一遍即可。