P1269 信号放大器

P1269 信号放大器

 

给一棵有根树,树的边上有距离。根上有一个信号发射器,会发生强度为 h 的信号,信号会往所有的节点传播,然而每经过
一条边强度就会削减距离的大小,当信号到达某点时小于 1,则信号传递失败。树上每个节点可以放信号放大器。信号经过放大
器后会被重新放大为 h。问至少要放多少个信号才能使每个点的信号都能传输成功,或者判断无解。
$n ≤ 20000$。

 

来自大佬的原话:树形$DP$显然。

我怎么看不出来呢?还是太蒟了。。。

 

设$f[u]$为传递整个子树$u$所需的最小信号,$g[u]$表示传递整个子树$u$所需要的最少的信号放大器

 

若不放放大器,则

$g[u]=\sum g[v]$

$f[u]=max(f[u],f[v]+dis[u,v])$

考虑放的情况:当$f[v]+dis[u,v]>h$时必须在$v$放一个信号放大器,则$f[u]=1,g[u]++$

时间复杂度$ O(n)$

 

%%GEOTCBRL%%

#include<iostream>
#include<cstdio>
#include<vector>
#include<cmath>
#include<cstdlib>

#define N 1010101
using namespace std;

int f[N],g[N],h,n;

vector<pair<int,int> >G[N];

bool flg=true;

void dfs(int u,int fa){
    int siz=G[u].size(),Tim=0,son=0;
    for(int i=0;i<siz;i++){
        int v=G[u][i].first,tim=G[u][i].second;
        if(v==fa){
            Tim=tim;
            continue;
        }
        if(tim>=h) {
            printf("No solution.\n");
            exit(0);
        }
        dfs(v,u);
        ++son;
        g[u]+=g[v];
        f[u]=max(f[u],f[v]+tim);
    }
    if(!son) g[u]=0,f[u]=1;
    else{
        if(u!=1&&f[u]+Tim>h){
            f[u]=1;
            g[u]++;
        }
    }
}

int main()
{
    scanf("%d",&n);
    for(int v,w,k,i=1;i<=n;i++){
        scanf("%d",&k);
        while(k--){
            scanf("%d%d",&v,&w);
            G[i].push_back(make_pair(v,w));
//            G[v].push_back(make_pair(i,w));
        }
    }
    scanf("%d",&h);
    dfs(1,0);
    
    printf("%d\n",g[1]);
    
    return 0;
}

 

posted @ 2018-10-09 17:59  清风我已逝  阅读(502)  评论(0编辑  收藏  举报