[ CodeVS冲杯之路 ] P1091
不充钱,你怎么AC?
题目:http://codevs.cn/problem/1091/
大家都写的 DFS,然而我想到了一种贪心的做法,重点是可以A
普遍的贪心是每次删掉该深度子树最大的点,但是如果有一边卡一条链就会WA
我们何不进一步考虑贪心,如果它下面是一条链我们就可以缓一缓到第 2 天再删是不是,反正它每次也就增加一个人
用 size[x] 记录所有后代加上自己的节点个数,f[x] 记录其最大子树的 size 值
我们考虑第一次不删这个节点,让它先扩展一次,然后第二次再删除它子树中 size 最大的节点
那么设 g[x]=size[x]-f[x],g 就为第一次不删,第二次删掉其最大的子树还剩余的节点数
一条链的 g[x]=1,而一个多叉节点的 g[x]>1,这就意味着先要删去 g 值更大的那个节点,才能不让它下一次扩展更多的出来
那么一层层地贪心,每次删掉 g 值最大的节点,直到不再继续传染为止
贪心跑得飞快~
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<stack>
using namespace std; const int N=;
stack<int> s,q;
int first[N],v[N*],next[N*],size[N],g[N],f[N];
void dfs(int x,int fa)
{
f[x]=fa;
int i;
for (i=first[x];i;i=next[i])
{
if (v[i]==fa) continue;
dfs(v[i],x);
if (size[v[i]]>g[x]) g[x]=size[v[i]];
}
size[fa]+=size[x];
}
int main()
{
int n,m,i,x,ans=;
scanf("%d%d",&n,&m);
for (i=;i<=m;i++)
{
scanf("%d%d",&x,&v[i]);
v[i+m]=x;
next[i]=first[x];
first[x]=i;
next[i+m]=first[v[i]];
first[v[i]]=i+m;
}
for (i=;i<=n;i++) size[i]=;
dfs(,);
for (i=;i<=n;i++) g[i]=size[i]-g[i];
s.push();
g[]=size[]=;
ans=n;
while (!s.empty())
{
m=;
while (!s.empty())
{
x=s.top();
s.pop();
for (i=first[x];i;i=next[i])
{
if (v[i]==f[x]) continue;
if (g[v[i]]>g[m]||(g[v[i]]==g[m]&&size[v[i]]>size[m])) m=v[i];
q.push(v[i]);
}
}
while (!q.empty())
{
x=q.top();
q.pop();
if (x==m) ans-=size[m];
else s.push(x);
}
}
printf("%d\n",ans);
return ;
}
这里有个DFS的:http://blog.csdn.net/yuyanggo/article/details/48087431
贪心的做法证明有人会严谨的吗?会的话告诉我谢谢!
[ CodeVS冲杯之路 ] P1091的更多相关文章
- [ CodeVS冲杯之路 ] P1368
不充钱,你怎么AC? 题目:http://codevs.cn/problem/1368/ 嗯……泡泡堂,很劲啊,其实就是个盗版的田忌赛马 http://www.cnblogs.com/hyfer/p/ ...
- [ CodeVS冲杯之路 ] P1092
不充钱,你怎么AC? 题目:http://codevs.cn/problem/1092/ 嗯,这道题有一定难度啊,需要先用扩展欧几里得算法求出逆元,然后按照大小构一颗带边权为小时数的树 树链剖分后在树 ...
- [ CodeVS冲杯之路 ] P3955
不充钱,你怎么AC? 题目:http://codevs.cn/problem/3955/ 最长上升子序列的加强版,n 有1000000,n 方的 DP 肯定会 TLE,那么用二分栈维护 二分栈我讲不好 ...
- [ CodeVS冲杯之路 ] P1165
不充钱,你怎么AC? 题目:http://codevs.cn/problem/1165/ 题目很简单,代码最好写朴实一点,不要想着哪些情况可以合并在一起啊等等 老老实实一个个判断,不然很容易出错 细节 ...
- [ CodeVS冲杯之路 ] P1053
不充钱,你怎么AC? 题目:http://codevs.cn/problem/1053/ 直接扫一遍串,把字母对应的 ascii 码直接做数组下标,交给数组统计 最后查询一遍数组的 'a'-'z' , ...
- [ CodeVS冲杯之路 ] P1171
不充钱,你怎么AC? 题目:http://codevs.cn/problem/1171/ 代码调了很久才调好啊,一开始题目都看错了(要是真的NOIP肯定没戏了QuQ) 后面发现CodeVS上的数据输入 ...
- [ CodeVS冲杯之路 ] P1197
不充钱,你怎么AC? 题目:http://codevs.cn/problem/1197/ 密钥的字母可以全转换为小写字母,然后一一映射,a→0,b→1,c→2,依此类推 对于密文只需将每一位减去对应密 ...
- [ CodeVS冲杯之路 ] P2492
不充钱,你怎么AC? 题目:http://codevs.cn/problem/2492/ 在此先orz小胖子,教我怎么路径压缩链表,那么这样就可以在任意节点跳进链表啦(手动@LCF) 对于查询操作,直 ...
- [ CodeVS冲杯之路 ] P2456
不充钱,你怎么AC? 题目:http://codevs.cn/problem/2456/ 用贪心的思想,木材当然要尽量分成多的木板,而大的木材能够分成大木板,但是小的木材不一定能够分成大的木板,所以木 ...
随机推荐
- Python 对象(type/object/class) 作用域 一等函数 (慕课--Python高级,IO并发 第二章)
在python中一共有两种作用域:全局作用域和函数作用域全局作用域:在全局都有效,全局作用域在程序执行时创建,在程序执行结束时销毁:所有函数以外的区域都是全局作用域:在全局作用域中定义的变量,都属于全 ...
- 虚拟机桥接模式下多台Ubuntu16.04系统互相连接
1.首先新建一个虚拟机并在该虚拟机上安装Ubuntu16.04系统.为这台虚拟机起名为Ubuntu3. 2.对Ubuntu3进行克隆,为新克隆生成的虚拟机起名为Ubuntu2.(这时我们会发现Ubun ...
- day2_作业1(购物车)
#!/usr/local/bin/python3 # -*- coding:utf-8 -*- balance=input("\033[36;1mPlease input your sala ...
- 学习python第十三天,函数5 装饰器decorator
定义:装饰器本质是函数,(装饰其他函数)就是为其他函数添加附加功能原则:1.不能修改被装饰的函数的源代码 2.不能修改装饰的函数的调用方式 实现装饰器知识储备1函数即变量2.高阶函数,满足2个条件之一 ...
- 希尔排序算法Java实现
希尔排序(Shell Sort)是插入排序的一种,它是针对直接插入排序算法的改进.该方法又称缩小增量排序,因DL.Shell于1959年提出而得名. 希尔排序实质上是一种分组插入方法.它的基本思想是: ...
- Git-Git库管理
对象和引用哪里去了? 从GitHub上克隆一个示例版本库,这个版本库在"历史穿梭"一章就已经克隆过一次了,现在要重新克隆一份.为了和原来的克隆相区别,克隆到另外的目录.执行下面的命 ...
- MySQL权限管理创建帐户
权限管理 1.创建账号 # 本地账号 create user 'egon1'@'localhost' identified by '123'; # mysql -uegon1 -p123 # 远程帐号 ...
- iOS笔记055 - UI总结01
1.程序启动后的开始动画 程序启动后可以加载一个简单的动画界面来介绍程序或者用户信息. 可以使用一个xib来描述界面.并且如果想在程序加载完成后第一个加载这个xib文件,需要在Appdelegat ...
- 每天一个Linux命令(7):pwd命令
pwd命令以绝对路径的方式显示用户当前工作目录. 语法 pwd(选项) 选项 --help:显示帮助信息: --version:显示版本信息. 实例 [root@localhost ~]# pwd / ...
- Python写的计算器程序(主要目的在于熟悉下正则表达式)
import res = '1-2*((60-30-(-40/5)*(9-2*5/3-7/3*99/4*2998-10*568/14.3))+(-4*3)/16-3)'s2 = 1-2*((60-30 ...