题意:给出一个树形结构,1号为根节点,每个节点都能接收和发射信号。每条边有一个消耗,若到达某个节点时信号值为负,则可以在它的父节点处放置一个信号放大器,使它的父节点发出的信号值等于根节点发出的信号值。
问如果可以使所有节点都接收到信号,需要的最少的信号放大器。否则输出""
思路:先 F a Fa Fa数组存下各个子节点到 n o w now now节点的距离,再遍历到根节点,再往上找以 n o w now now节点为子树的深度,用 d i s dis dis数组存起来,。返回到 n o w now now节点时,如果 d i s [ n o w ] + F a [ n o w ] > m dis[now]+Fa[now]>m dis[now]+Fa[now]>m,表示在 n o w now now节点的父节点 f a fa fa节点发出的信号不能完全覆盖 n o w now now子树,说明在 f a fa fa节点必须放一个信号放大器。 d i s [ n o w ] dis[now] dis[now]就应该改成 0 0 0。
#include<bits/stdc++.h>
using namespace std;
const int N = 20010;
const int inf = 0x7ffffff;
int head[N], tot = 1, ans = 0;
int dis[N], Fa[N];
struct tree{
int to, next, v;
} t[N<<1];
void add(int x, int y, int we) {
//图的存储
t[tot].to = y , t[tot].next = head[x], t[tot].v = we, head[x] = tot++;
}
void dfs(int now, int fa, int m) {
//dfs遍历
for(int i=head[now]; i != 0; i=t[i].next) {
if(t[i].to != fa) {
Fa[t[i].to] = t[i].v;//记录节点到其父亲的深度
dfs(t[i].to, now, m);//往下遍历
dis[now] = max(dis[t[i].to]+t[i].v, dis[now]);//找子树深度
}
}
if(Fa[now] + dis[now] > m) ans++, dis[now] = 0;//判断是否要放信号放大器。
}
int main() {
int n, m, x, y, f = 0;
cin >> n;
for(int i=1; i<=n; i++) {
cin >> m;
for(int j=0; j<m; j++) {
cin >> x >> y;
f = max(f, y);
add(i, x, y);
}
}
cin >> m;
if(f >= m) {
cout << "No solution."; return 0;}//特判,不能完全覆盖的情况
dfs(1, 0, m);
cout << ans;
return 0;
}