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(){ 这个题一看就是图论题,然后我们观察他的性质,因为一个图论题如果没有什么性质,就是真· ...
随机推荐
- IE8以下不支持getElementsByClassName方法
function getElementsByClassName(classStr,tagName,element){ tagName = (tagName || '*'); element = (el ...
- nfs服务部署记录
一.概念介绍NFS 是Network File System的缩写,即网络文件系统.一种使用于分散式文件系统的协定,由Sun公司开发,于1984年向外公布.功能是通过网络让不同的机器.不同的操作系统能 ...
- web.config connectionStrings 数据库连接字符串的解释(转载)
先来看一下默认的连接SQL Server数据库配置 1.默认生成 <connectionStrings> <add name="Exa*DB" connectio ...
- usb驱动开发22之驱动生命线
我们总是很喜欢高潮,不是吗?那就好好对待她哦.我们来看一下linux中的高潮部分设备是怎么从Address进入Configured的. usb_set_configuration函数的代码就不贴了,可 ...
- 尝试HTML + JavaScript 编写Windows App
一直以来博文中使用最多的就是C# + XAML.进入Windows App时代,又多了一对 Javascript + HTML组合,这对于Web开发的程序员来说再熟悉不过了.其实小编也做过几年的Web ...
- 【转】Sql Server参数化查询之where in和like实现详解
转载至:http://www.cnblogs.com/lzrabbit/archive/2012/04/22/2465313.html 文章导读 拼SQL实现where in查询 使用CHARINDE ...
- (原创)解决Excel 互操作错误"检索COML类工厂中 CLSID为 {00024500-0000-0000-C000-000000000046}的组件时失败,原因是出现以下错误: 80070005"
最近在.net中处理Excel文件数据导入时报出以下错误: 检索COML类工厂中 CLSID为 {00024500-0000-0000-C000-000000000046}的组件时失败,原因是出现以下 ...
- 线程本地变量ThreadLocal源码解读
一.ThreadLocal基础知识 原始线程现状: 按照传统经验,如果某个对象是非线程安全的,在多线程环境下,对对象的访问必须采用synchronized进行线程同步.但是Spring中的各种模板 ...
- 使用Netty绑定一个端口如何分辨出多种类型的DTU的注册包
一. 背景 项目需要使用Netty和DTU(无线数据传输模块)通信,需要接入多种类型的DTU,每种dtu连接上来之后都首先会发送一个注册报文.需要解析该注册报文来实现: 1. 分辨出是哪种类型的dt ...
- 关于code reiview
先谈谈三个code review的关键因素: 一.创建review要简单 code reivew是一个程序员日常工作中经常做的一件事,理论上来讲,任何一个将要submit到SCM的change,都必须 ...