[jzoj1029] 【NOIP动态规划专题】电子眼 {树形dp}

题目

Description
中山市石一个环境优美、气候宜人的小城市。因为城市的交通并不繁忙,市内的道路网很稀疏。准确地说,中山市有N条马路和N个路口,每条马路连接两个路口,每两个路口之间最多只有一条马路。作为一条交通网络,显然每两个路口之间都是可达的。为了更好地管理中山市的交通,市长决定在一些路口加装电子眼,用来随时监视路面情况。这些装在路口的电子眼能够监视所有连接到这个路口的马路。现在市长想知道最少需要在多少个路口安装电子眼才能监视所有的马路。市长已经把所有的路口都编上了1~N的号码。 给你中山市的地图,你能帮忙吗?

Input
输入文件第1行包括一个数字N(1<=N<=100000),表示中山市的路口数。接下来N行,第i+1行的第一个数字ki表示有ki条马路与路口i相连,后面紧跟着ki个数字,表示与路口i直接相连的路口。

Output
输出最少需要安装电子眼的数量。


解题思路

f[i] f [ i ] 表示不选i节点时最少安装电子眼的数量
g[i] g [ i ] 表示选i节点时最少安装电子眼的数量
我们可以遍历整一棵树,在回溯的时候判断,动态转移方程为:

f[i]=g[(i)] f [ i ] = g [ ( i 的 根 节 点 ) ] 它 的 根 节 点 必 须 选

g[i]=1+min(g[(i)],f[(i)]) g [ i ] = 1 + m i n ( g [ ( i 的 根 节 点 ) ] , f [ ( i 的 根 节 点 ) ] ) 它 的 根 节 点 可 选 也 可 不 选


代码

#include<cstdio>
#include<algorithm>
using namespace std; 
struct node{
    int y,next; 
}a[200001];
int len,n,last[200001],f[200001],g[200001]; bool b[200001]; 
void dp(int k)
{
    int q=1,w=0; 
    for (int i=last[k];i;i=a[i].next)
    {
        if (!b[a[i].y]) {
            b[a[i].y]=1; 
            dp(a[i].y); 
            q+=min(f[a[i].y],g[a[i].y]);
        } 
        w+=g[a[i].y]; 
    }
    g[k]=q; 
    f[k]=w; 
}
int main()
{
    scanf("%d",&n); 
    int x,z;
    for (int i=1;i<=n;i++)
     {
        scanf("%d",&z); 
        for (int j=1;j<=z;j++)
        {
           scanf("%d",&x);  
           a[++len]={x,last[i]}; last[i]=len; 
        }
     }
    b[1]=1; dp(1); 
    printf("%d",min(f[1],g[1])); 
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值