BZOJ 1124: [POI2008]枪战Maf
1124: [POI2008]枪战Maf
Time Limit: 10 Sec Memory Limit: 162 MB
Submit: 617 Solved: 236
[Submit][Status][Discuss]
Description
有n个人,每个人手里有一把手枪。一开始所有人都选定一个人瞄准(有可能瞄准自己)。然后他们按某个顺序开枪,且任意时刻只有一个人开枪。因此,对于不同的开枪顺序,最后死的人也不同。
Input
输入n人数<1000000 每个人的aim
Output
你要求最后死亡数目的最小和最大可能
Sample Input
2 3 2 2 6 7 8 5
Sample Output
HINT
Source
分析
很有意思的一道贪心题目,主要是代码实现上的细节挺多,要不就是今晚太困了……
两个问题要分开分析,有不同的贪心思路。
首先,枪杀关系类似于有向图。按照联通块进行划分,其可以分为大致三种情况——
单独一个点形成的自环。显然这个点必定会死,不论是最多死亡人数还是最少死亡人数,都会使答案+1。
一条链,最后的一个点可能是个自环,类似于1->2->3->4->5->5。显然这条链上除了1,其他点通过合理的顺序都可以被枪杀,所以最多死亡人数是len-1。因为1不会死,我们贪心的让1先杀死2,这样3就可以活下来;因为3可以活下来,所以贪心的杀死4,这样5就可以活下来。依次类推,得到一个贪心思路——如果当前认为一个点可以活,则贪心的杀死他的枪杀目标,给他枪杀目标的目标以更大的生存机会。如果这样发现,其枪杀目标的目标已经没有入边,则认为其也是可以活下来的,继续这一过程。
最为复杂的是基环内向树和简单的有向环。如果是环,那么至少要有一个点活着,最多只能有(size/2)个点活着。而如果是基环树,至少每条链的尾端要活着,至多可以做到类似于上面的贪心。
代码
#include <bits/stdc++.h>
using namespace std; #define N 1000100 int n, to[N], ans1, ans2; namespace query1
{
int cnt[N];
int vis[N];
int que[N]; void solve(void)
{
ans1 = n; memset(cnt, , sizeof(cnt));
memset(vis, , sizeof(vis)); for (int i = ; i <= n; ++i)
++cnt[to[i]]; for (int i = ; i <= n; ++i)
if (i == to[i])
--cnt[i], vis[i] = ; int head = , tail = ; for (int i = ; i <= n; ++i)
if (!vis[i] && !cnt[i])
que[tail++] = i; while (head != tail)
{
int top = que[head++]; vis[top] = ; --ans1; if (!vis[to[top]])
{
vis[to[top]] = ; if (!vis[to[to[top]]] && --cnt[to[to[top]]] == )
que[tail++] = to[to[top]];
}
} for (int i = ; i <= n; ++i)
if (!vis[i])
{
int siz = ; for (int j = i; !vis[j]; j = to[j])
vis[j] = , ++siz; ans1 -= (siz >> );
}
}
} namespace query2
{
int cnt[N];
int vis[N];
int que[N];
int flg[N]; void solve(void)
{
ans2 = n; memset(cnt, , sizeof(cnt));
memset(vis, , sizeof(vis));
memset(flg, , sizeof(flg)); for (int i = ; i <= n; ++i)
++cnt[to[i]]; for (int i = ; i <= n; ++i)
if (i == to[i])
--cnt[i], vis[i] = ; int head = , tail = ; for (int i = ; i <= n; ++i)
if (!vis[i] && !cnt[i])
que[tail++] = i, --ans2; while (head != tail)
{
int top = que[head++]; flg[to[top]] = vis[top] = ; if (--cnt[to[top]] == )
que[tail++] = to[top];
} for (int i = ; i <= n; ++i)
if (!vis[i])
{
int flag = ; for (int j = i; !vis[j]; j = to[j])
vis[j] = , flag |= flg[j]; if (!flag)--ans2;
}
}
} signed main(void)
{
scanf("%d", &n); for (int i = ; i <= n; ++i)
scanf("%d", to + i); query1::solve();
query2::solve(); printf("%d %d\n", ans1, ans2);
}
BZOJ_1124.cpp
@Author: YouSiki
BZOJ 1124: [POI2008]枪战Maf的更多相关文章
- bzoj 1124 [POI2008]枪战Maf 贪心
[POI2008]枪战Maf Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 741 Solved: 295[Submit][Status][Disc ...
- BZOJ 1124: [POI2008]枪战Maf(构造 + 贪心)
题意 有 \(n\) 个人,每个人手里有一把手枪.一开始所有人都选定一个人瞄准(有可能瞄准自己).然后他们按某个顺序开枪,且任意时刻只有一个人开枪. 因此,对于不同的开枪顺序,最后死的人也不同. 问最 ...
- 【刷题】BZOJ 1124 [POI2008]枪战Maf
Description 有n个人,每个人手里有一把手枪.一开始所有人都选定一个人瞄准(有可能瞄准自己).然后他们按某个顺序开枪,且任意时刻只有一个人开枪.因此,对于不同的开枪顺序,最后死的人也不同. ...
- 【BZOJ】1124: [POI2008]枪战Maf
题意 \(n(n < 1000000)\)个人,每个人\(i\)指向一个人\(p_i\),如果轮到\(i\)了且他没死,则他会将\(p_i\)打死.求一种顺序,问死的人最少和最多的数目. 分析 ...
- [POI2008]枪战Maf
[POI2008]枪战Maf 题目 有n个人,每个人手里有一把手枪.一开始所有人都选定一个人瞄准(有可能瞄准自己).然后他们按某个顺序开枪,且任意时刻只有一个人开枪.因此,对于不同的开枪顺序,最后死的 ...
- 【BZOJ1124】[POI2008]枪战Maf 贪心+思路题
[BZOJ1124][POI2008]枪战Maf Description 有n个人,每个人手里有一把手枪.一开始所有人都选定一个人瞄准(有可能瞄准自己).然后他们按某个顺序开枪,且任意时刻只有一个人开 ...
- [POI2008]枪战Maf题解
问题 C: [POI2008]枪战Maf 时间限制: 1 Sec 内存限制: 256 MB 题目描述 有n个人,每个人手里有一把手枪.一开始所有人都选定一个人瞄准(有可能瞄准自己).然后他们按某个顺 ...
- BZOJ1124 [POI2008]枪战Maf[贪心(证明未完成)+拓扑排序]
吐槽:扣了几个小时,大致思路是有了,但是贪心的证明就是不会, 死磕了很长时间,不想想了,结果码代码又不会码.. 深深体会到自己码力很差,写很多行还没写对,最后别人代码全一二十行,要哭了 以下可能是个人 ...
- 【BZOJ 1124】[POI2008] 枪战Maf Tarjan+树dp
#define int long long using namespace std; signed main(){ 这个题一看就是图论题,然后我们观察他的性质,因为一个图论题如果没有什么性质,就是真· ...
随机推荐
- Mysql备份系列(1)--备份方案总结性梳理
mysql数据库备份有多么重要已不需过多赘述了,废话不多说!以下总结了mysql数据库的几种备份方案: 一.binlog二进制日志通常作为备份的重要资源,所以再说备份方案之前先总结一下binlog日志 ...
- curl命令
定位后端接口是否ok,经常使用到curl -b/cookie <name=string/file> cookie字符串或文件读取位置 curl http://localhost --co ...
- Activity中获取view的高度和宽度为0的原因以及解决方案
在activity中可以调用View.getWidth.View.getHeight().View.getMeasuredWidth() .View.getgetMeasuredHeight()来获得 ...
- vbs keys
其使用格式为: object.SendKeys string "object":表示WshShell对象 "string":表示要发送的按键指令字符串,需要放在 ...
- Incorrect string value异常解决
mysql数据库的一个问题 1366-Incorrect string value:'\xE5\x8D\xA1\xE5......' for column 'filename' at row 1 问题 ...
- Oracle 数据库日常巡检
1. 检查数据库基本状况 包含:检查Oracle实例状态,检查Oracle服务进程,检查Oracle监听进程,共三个部分. 1.1. 检查Oracle实例状态 select instance_name ...
- 在线音乐网站【03】Part one 功能实现
今天打算把网站功能的具体实现给总结一下,如果你想了解整个小项目,建议你先看看前面2篇博客. 1.在线音乐网站(1)需求和功能结构 2.在线音乐网站(2)数据库和开发环境 7.网站主要模块实现 a.在线 ...
- Linux学习笔记-Ubuntu添加右键菜单打开终端
1.进入个人目录(如/home/batsing,下文缩写成 ~ ):设置显示隐藏文件,或使用命令行:2.进入 ~/.gnome2/nautilus-scripts 文件夹,新建一个文件,名为 term ...
- SQL基础之select
1.认识select select的主要语法如下,这个很重要因为只有记住了整体的结构才能应对任何情况.从中可以看到select的强大主要就是建立在where.group by.having.order ...
- JavaScript中的类型转换(二)
说明: 本篇主要讨论JavaScript中各运算符对运算数进行的类型转换的影响,本文中所提到的对象类型仅指JavaScript预定义的类型和程序员自己实现的对象,不包括宿主环境定义的特殊对象(比如浏览 ...