• 电子眼【树形dp】


    题目大意:

    题目链接:http://10.156.17.250/JudgeOnline/showproblem?problem_id=2119 (学校局域网)
    在一棵树中选择一些点使得每条边至少与一个选择的点相邻。


    思路:

    很显然的树形dpdp
    f[x][1/0]f[x][1/0]表示以节点xx为根,选或不选这个点的最少选择数量。
    显然如果不选择这个点,那么这个点的所有儿子节点都必须选,否则这个点的子节点选择或不选都可以。
    方程如下
    f[x][0]=f[y][1]   (yson[x])f[x][0]=sum f[y][1] (yin son[x])
    f[x][1]=(min(f[y][0],f[y][1]))+1   (yson[x])f[x][1]=(sum min(f[y][0],f[y][1]))+1 (yin son[x])

    特别的,当n=1n=1时直接输出1就可以了。


    代码:

    #include <cstdio>
    #include <iostream>
    using namespace std;
    
    const int N=100010;
    int n,x,y,tot,in[N],head[N],f[N][2];
    
    struct edge
    {
    	int next,to;
    }e[N*2];
    
    void add(int from,int to)
    {
    	e[++tot].to=to;
    	e[tot].next=head[from];
    	head[from]=tot;
    }
    
    void dp(int x,int fa)
    {
    	f[x][1]=1;
    	for (int i=head[x];~i;i=e[i].next)
    	{
    		int y=e[i].to;
    		if (y==fa) continue;
    		dp(y,x);
    		f[x][0]+=f[y][1];
    		f[x][1]+=min(f[y][0],f[y][1]);
    	}
    }
    
    int main()
    {
    	memset(head,-1,sizeof(head));
    	scanf("%d",&n);
    	if (n==1) return !printf("1");
    	for (int i=1;i<n;i++)
    	{
    		scanf("%d%d",&x,&y);
    		add(x,y);
    		add(y,x);
    		in[x]++;
    		in[y]++;
    	}
    	dp(1,0);
    	printf("%d",min(f[1][0],f[1][1]));
    	return 0;
    }
    
  • 相关阅读:
    python的struct模块
    Linux程序设计学习笔记(独乐乐版)
    理解AndroidX
    Android中的样式和主题
    Android中Fragment的使用
    Android 中Dialog的使用
    直接在apk中添加资源的研究
    Android签名生成和互转
    简单扒一下Volley源码,扩展Volley生命周期
    获取android所有联系人信息
  • 原文地址:https://www.cnblogs.com/hello-tomorrow/p/11998276.html
Copyright © 2020-2023  润新知