[POI2008]枪战Maf题解
问题 C: [POI2008]枪战Maf
时间限制: 1 Sec 内存限制: 256 MB
题目描述
有n个人,每个人手里有一把手枪。一开始所有人都选定一个人瞄准(有可能瞄准自己)。然后他们按某个顺序开枪,且任意时刻只有一个人开枪。因此,对于不同的开枪顺序,最后死的人也不同。
输入
输入n人数<1000000 每个人的aim
输出
你要求最后死亡数目的最小和最大可能
样例输入
8
2 3 2 2 6 7 8 5
样例输出
3 5
本次考试最后一个题,被老师评论称难炸了……然而貌似不那么难,但你绝对打不A。
这道题只能怪我代码能力太弱,该想到的都想到了,然而还是华丽丽的爆了0。
首先让我们先明确几条性质来帮助我们做题:
- 对于每个连通图,他至少有一个环或者一个人自杀。缩完点之后它是树或树林。证明:假设我们已经输入了n个人,先忽略一下第n个人要杀谁,如果之前没有人自杀或环的话它一定是一棵树,因为有n个点和n-1条边,那么第n个人指向哪里就很关键了,他指向每一个其他人都会形成一个环,而指向他自己又是自杀,所以,第一条get。
- 每一个没人杀的人都会存活,每一个自杀的人最终都会死。不解释。
- 每个人对于答案的影响不在于他被谁杀掉,而在于他杀掉谁,世界不关心你说了什么,世界只关心你做了什么。
- 一个环如果没人干预,那么它最少死n/2个人,向下取整。也就是一个人如果不杀人就只能被杀死,对于奇数个点的环你杀了人也可能被杀死。最多就是总人数-1。
- 一个环如果有人干预,那么它最多就是全部被杀,最小在下面说。
- 如果一个人没死,那么他指向的那个人就一定会死,如果指向那个人的人都死了,那么他就可以活下来,这一点在环中同样适用。
为了方便,我们直接去求活着的人数,反正人不是活着就是死了废话。
先说死的人最少,那么入度为0的人一定活下来了,因此我们用队列慢慢往上爬即可,只要队列中的人他所杀的人要杀的人没人杀他了,那么他也可以入队。至于没人指向的环嘛,上面说了。
死的最多的人就是让人们从树顶从上往下开枪,直到叶子节点所以答案就为缩完点后入度为0的点。
我打完之后只过了一个点,因为这题有两个坑点,至少对我来说是这样的。
第一,指向这个点的点可以有好几个,但这个点的出度只有一个,虽然是废话,但在你判断谁存活的时候需要先判断一下,你目前队首的这个点所指向的点是否已经被杀掉,否则错炸了。
第二,也是卡住了无数英雄好汉的点,如何判断某个环是否已被用队列访问,开个bool记录看似容易,然而在哪里打标记就是大坑了,对于WA的童鞋们可以试一下这个点:
4
2 3 2 3
希望能帮到你们,在这个点中,环中每个人都死了,但如果你在将某个元素塞进队列时才将它打上标记你会发现实际已经访问了的环并未被打上标记,因此,正解是每个被塞进队列的人他所指向的人和他所指向的人所指向的人都要被打上标记。
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
#include<cmath>
using namespace std;
int n,tt[],st[],top;
bool rz[],rz2[];
int dfn[],low[],zz1;
int zz2,belong[],sum[];
void tar(int x){
zz1++;
top++;
st[top]=x;
rz[x]=rz2[x]=;
dfn[x]=low[x]=zz1;
if(!rz2[tt[x]])
{
tar(tt[x]);
low[x]=min(low[x],low[tt[x]]);
}
else if(rz[tt[x]])
{
low[x]=min(low[x],dfn[tt[x]]);
}
if(dfn[x]==low[x])
{
int v;
zz2++;
do{
v=st[top];
top--;
rz[v]=;
sum[zz2]++;
belong[v]=zz2;
}while(dfn[v]!=low[v]);
}
}
int a[],zz3,rd2[],be[];
bool fw[],js[];
int rd[],ans1,ans2;
queue<int> q1;
int main(){
scanf("%d",&n);
for(int i=;i<=n;i++)
{
scanf("%d",&tt[i]);
rd[tt[i]]++;
}
for(int i=;i<=n;i++)
if(!rz2[i])
tar(i);
for(int i=;i<=n;i++)
{
if(rd[i]==)
{
ans1++;
q1.push(i);
fw[belong[i]]=;
}
}
while(!q1.empty())
{
int x=q1.front();
q1.pop();
fw[belong[tt[x]]]=;
if(!js[tt[x]])
{
js[tt[x]]=;
rd[tt[tt[x]]]--;
if(rd[tt[tt[x]]]==)
{
ans1++;
fw[belong[tt[tt[x]]]]=;
q1.push(tt[tt[x]]);
}
}
}
for(int i=;i<=zz2;i++)
{
if(!fw[i])
{
ans1+=sum[i]/;
}
}
for(int i=;i<=n;i++)
{
if(belong[tt[i]]!=belong[i]||tt[i]==i)
{
rd2[belong[tt[i]]]++;
}
}
for(int i=;i<=zz2;i++)
{
if(!rd2[i])
ans2++;
}
printf("%d %d",n-ans1,n-ans2);
return ;
}
对了,这道题打法不只一种,有兴趣的读者可以试一试别的方法,DP已被验证可行,贪心据说也可以,希望读者不要拘泥于一种打法。
[POI2008]枪战Maf题解的更多相关文章
- 【BZOJ1124】[POI2008]枪战Maf 贪心+思路题
[BZOJ1124][POI2008]枪战Maf Description 有n个人,每个人手里有一把手枪.一开始所有人都选定一个人瞄准(有可能瞄准自己).然后他们按某个顺序开枪,且任意时刻只有一个人开 ...
- BZOJ1124 [POI2008]枪战Maf[贪心(证明未完成)+拓扑排序]
吐槽:扣了几个小时,大致思路是有了,但是贪心的证明就是不会, 死磕了很长时间,不想想了,结果码代码又不会码.. 深深体会到自己码力很差,写很多行还没写对,最后别人代码全一二十行,要哭了 以下可能是个人 ...
- BZOJ 1124: [POI2008]枪战Maf
1124: [POI2008]枪战Maf Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 617 Solved: 236[Submit][Status ...
- [POI2008]枪战Maf
[POI2008]枪战Maf 题目 有n个人,每个人手里有一把手枪.一开始所有人都选定一个人瞄准(有可能瞄准自己).然后他们按某个顺序开枪,且任意时刻只有一个人开枪.因此,对于不同的开枪顺序,最后死的 ...
- bzoj 1124 [POI2008]枪战Maf 贪心
[POI2008]枪战Maf Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 741 Solved: 295[Submit][Status][Disc ...
- bzoj1124[POI2008]枪战maf
这代码快写死我了.....死人最多随便推推结论.死人最少,每个环可以单独考虑,每个环上挂着的每棵树也可以分别考虑.tarjan找出所有环,对环上每个点,求出选它和不选它时以它为根的树的最大独立集(就是 ...
- 【BZOJ】1124: [POI2008]枪战Maf
题意 \(n(n < 1000000)\)个人,每个人\(i\)指向一个人\(p_i\),如果轮到\(i\)了且他没死,则他会将\(p_i\)打死.求一种顺序,问死的人最少和最多的数目. 分析 ...
- BZOJ 1124: [POI2008]枪战Maf(构造 + 贪心)
题意 有 \(n\) 个人,每个人手里有一把手枪.一开始所有人都选定一个人瞄准(有可能瞄准自己).然后他们按某个顺序开枪,且任意时刻只有一个人开枪. 因此,对于不同的开枪顺序,最后死的人也不同. 问最 ...
- 【BZOJ1124】[POI2008]枪战Maf(基环树_构造)
被教练勒令做题不能看题解后的第一道新题,自行 yy 了好久终于 AC 了(菜啊)--写博客纪念. 题目: BZOJ1124 分析: 考虑每个人向他要打的人连边.根据题意,所有点都有且只有一条出边.那么 ...
随机推荐
- 自动启动 Windows 10 UWP 应用
原文: https://docs.microsoft.com/zh-cn/windows/uwp/xbox-apps/automate-launching-uwp-apps 简介 开发人员有多种选项可 ...
- Android零基础入门第32节:新推出的GridLayout网格布局
原文:Android零基础入门第32节:新推出的GridLayout网格布局 本期主要学习的是网格布局是Android 4.0新增的布局,和前面所学的TableLayout表格布局 有点类似,不过他有 ...
- Windows 10 版本信息
原文 https://technet.microsoft.com/zh-cn/windows/release-info Windows 10 版本信息 Microsoft 已更新其服务模型. 半年频道 ...
- LCID
Language Location (or type) Language ID Language tag Supported version Afar 0x1000 aa Release 9 Af ...
- Android零基础入门第71节:CardView简单实现卡片式布局
还记得我们一共学过了多少UI控件了吗?都掌握的怎么样啊. 安卓中一些常用控件学习得差不多了,今天再来学习一个新的控件CardView,在实际开发中也有非常高的地位. 一.CardView简介 Card ...
- 中国自主X86处理器工艺跃进:国产28nm升级16nm(上海兆芯)
提到X86处理器,世人皆知Intel.AMD,殊不知还有个VIA(威盛),在Intel反垄断世纪大战中VIA公司作为Intel霸权的受害者也最终确认了X86授权,不过VIA与前面两家的实力相差太远,X ...
- 把握每次机会,麒麟芯片5年成就高端(SoC包括AP、基带、ISP等,华为确实牛)
从2016年11月华为Mate 9 /Mate 9 Pro发布,到2017年2月荣耀V9和华为P10 /P10 Plus 相继发布,这几款都是华为和荣耀的高端旗舰机型,且搭载的都是华为最新旗舰芯片-- ...
- 进程交互还可以使用QSharedMemory
官方例子: http://doc.qt.io/qt-5/qtcore-ipc-sharedmemory-example.html 查了一下,QSharedMemory没有自带任何信号.我的想法: 1. ...
- Linux下C/C++帮助手册安装方法
1. 安装C的帮助手册 如果你使用的Linux发行版, 默认没有安装C语言的库函数MAN手册, 使用下面的方法解决: # sudo apt-get install manpages # sudo a ...
- 针对TianvCms的搜索优化文章源码(无版权, 随便用)
介绍: 搜索优化虽然不是什么高深的技术, 真正实施起来却很繁琐, 后台集成搜索优化的文章可以便于便于管理, 也让新手更明白优化的步奏以及优化的日常. 特点: 根据自己的经验和查阅各种资料整理而成, 相 ...