• CF1029E


    一个看起来就不对的贪心居然是正解...

    但仔细思考一下,这种贪心倒的确找不到反例..

    贪心思想:每次找出离根节点最远的点,然后由根节点向这个点的父节点连边,一直连到所有点都能被覆盖即可,这样构造出的一定是一个可行的最优解

    正确性证明(个人YY):

    主要是要证明这种做法的最优性:

    首先,由于所有点都要求被覆盖,自然离根节点最远的点也不例外

    那么,如果想覆盖上离根节点最远的点,只会有两种覆盖方法:一种是将根节点与这个点本身相连,另一种是将根节点与这个点的父节点相连

    不难发现,将根节点与这个点的父节点相连,这样的方案一定不会差

    证明:假设这个父节点还有别的子节点,那么与父节点相连后这些子节点都能被覆盖,这样一定是更优的

    而即使这个父节点没有别的子节点,他还有自己的父节点,这样连边也能减少根节点与他的父节点的距离,也会达到更好的效果

    即使上面两点都没有起作用,至少这样还可以覆盖上最远的点,也并不会使代价增大,所以这样做是完全可行的。

    这样就完事了

    (ps:树上bfs真好用)

    #include <cstdio>
    #include <cmath>
    #include <cstring>
    #include <cstdlib>
    #include <iostream>
    #include <algorithm>
    #include <queue>
    #include <stack>
    using namespace std;
    struct Edge
    {
    	int next;
    	int to;
    }edge[400005];
    bool used[200005];
    int head[200005];
    int f[200005];
    int n;
    int cnt=1;
    void init()
    {
    	memset(head,-1,sizeof(head));
    	cnt=1;
    }
    void add(int l,int r)
    {
    	edge[cnt].next=head[l];
    	edge[cnt].to=r;
    	head[l]=cnt++;
    }
    struct node
    {
    	int num;
    	int dep;
    }p[200005];
    void bfs(int rt)
    {
    	queue <int> M;
    	p[rt].dep=0;
    	p[rt].num=rt;
    	M.push(rt);
    	while(!M.empty())
    	{
    		int u=M.front();
    		M.pop();
    		for(int i=head[u];i!=-1;i=edge[i].next)
    		{
    			int to=edge[i].to;
    			if(p[to].dep)
    			{
    				continue;
    			}
    			p[to].dep=p[u].dep+1;
    			p[to].num=to;
    			f[to]=u;
    			M.push(to);
    			if(p[to].dep<=2)
    			{
    				used[to]=1;
    			}
    		}
    	}
    }
    bool cmp(node a,node b)
    {
    	return a.dep>b.dep;
    }
    int main()
    {	
    	scanf("%d",&n);
    	init();
    	for(int i=1;i<n;i++)
    	{
    		int x,y;
    		scanf("%d%d",&x,&y);
    		add(x,y);
    		add(y,x);
    	}
    	bfs(1);
    	sort(p+1,p+n+1,cmp);
    	int ans=0;
    	for(int i=1;i<=n;i++)
    	{
    		if(used[p[i].num])
    		{
    			continue;
    		}
    		ans++;
    		int u=f[p[i].num];
    		used[u]=1;
    		for(int j=head[u];j!=-1;j=edge[j].next)
    		{
    			int to=edge[j].to;
    			used[to]=1;
    		}
    	}
    	printf("%d
    ",ans);
    	return 0;
    }
  • 相关阅读:
    Pandas(二)描述统计与函数应用
    Pandas(一)数据结构和基本功能
    Numpy(下)
    Numpy(上)
    42th 逻辑的连续性 取决于 细节的理解-------------我是个厨子:类的调用vs 对象调用方法
    40th 要掀桌子么 还是尬坐吧
    爱的 大循环 :我爱世界杯
    39th 迷迷糊糊 二豆玩不转了
    Python中的可迭代对象
    爱的传送带: print(.format())
  • 原文地址:https://www.cnblogs.com/zhangleo/p/10764170.html
Copyright © 2020-2023  润新知