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(){ 这个题一看就是图论题,然后我们观察他的性质,因为一个图论题如果没有什么性质,就是真· ...
随机推荐
- Anyconnect的VPN环境部署(2)-在Linux客户机上连接Anyconnect
由于之前已经在机房IDC安装了Anyconnect的VPN服务环境(参考:Anyconnect的VPN环境部署(1)-OpenConnect server(ocserv)服务安装)今天介绍下在linu ...
- 源码安装mysql
1. 安装依赖组件 # yum install gcc gcc-c++ ncurses-devel perl -y 2. 安装cmake # wget http://www.cmake.org/f ...
- Java 集合系列07之 Stack详细介绍(源码解析)和使用示例
概要 学完Vector了之后,接下来我们开始学习Stack.Stack很简单,它继承于Vector.学习方式还是和之前一样,先对Stack有个整体认识,然后再学习它的源码:最后再通过实例来学会使用它. ...
- 【WPF】TextBox样式重写注意事项
1.普通控件重写需要添加一行 <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="C ...
- Java的注解(Annotation)
1.什么是注解 Annotation is code about the code, that is metadata about the program itself. Java注解,是Java5. ...
- SpringMVC源码分析系列
说到java的mvc框架,struts2和springmvc想必大家都知道,struts2的设计基本上完全脱离了Servlet容器,而springmvc是依托着Servlet容器元素来设计的,同时sp ...
- FineUI小技巧(3)表格导出与文件下载
需求描述 实际应用中,我们可能需要导出表格内容,或者在页面回发时根据用户权限下载文件(注意,这里的导出与下载,都是在后台进行的,和普通的一个链接下载文件不同). 点击按钮导出表格 由于FineUI 默 ...
- Python2.5-原理之模块
此部分来自于<Python学习手册>第五部分 一.模块(21章) 模块是最高级别的程序组织单元,它将程序代码和数据封装起来以便重用..模块往往对应于python程序文件.每个文件就是一个模 ...
- 分享:关于之前锤子手机刷MIUI之后,现在有事跌宕起伏的刷回了Smartisan OS!
序言: 距离上次把锤子手机刷成MIUI之后已经一个半月了,我是一个刷机党,一个半月足够让我适应一个系统,了解一个系统.刷机有风险,不过我愿意冒这个风险,因为兴趣,没别的.刷机之后,肯定是有问题的,没 ...
- jQuery操作单选按钮(radio)用法
1.获取选中值,四种方法都可以: $('input:radio:checked').val():$("input[type='radio']:checked").val(); $( ...