[POI2008]枪战Maf
[POI2008]枪战Maf
题目
有n个人,每个人手里有一把手枪。一开始所有人都选定一个人瞄准(有可能瞄准自己)。然后他们按某个顺序开枪,且任意时刻只有一个人开枪。因此,对于不同的开枪顺序,最后死的人也不同。
INPUT
输入n人数<1000000 每个人的aim
OUTPUT
你要求最后死亡数目的最小和最大可能
SAMPLE
INPUT
8
2 3 2 2 6 7 8 5
OUTPUT
3 5
解题报告
考试时候打出了tarjan,然而不会用= =
正解:
tarjan
我们分连通块来考虑
首先自杀的一定死
一个环上的,最多死 点数-1 个(一个人开始开枪,然后被杀,最后只剩一个),最少死一半(假如少于一半,那么必然有至少一条直接相连的边没有被砍,必然还会死人)
一个环加上内向树,最多死 点数-入度为0的个数
最少如何处理呢?
入度为0的死不了(没人打他)
将他们推入队列,他们的目标一定死,那就让他们死,然后他们的目标入度减1,看看是否变为入度为0,依次处理
最后剩下的一定是一堆环
然后就可以在欢声笑语中打出GG
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<queue>
using namespace std;
inline int read(){
int sum();
char ch(getchar());
for(;ch<''||ch>'';ch=getchar());
for(;ch>=''&&ch<='';sum=sum*+(ch^),ch=getchar());
return sum;
}
int n;
struct edge{
int s,e,n;
}a[];
int pre[],tot;
inline void insert(int s,int e){
a[++tot].s=s;
a[tot].e=e;
a[tot].n=pre[s];
pre[s]=tot;
}
inline int my_max(int a,int b){
return a>b?a:b;
}
inline int my_min(int a,int b){
return a<b?a:b;
}
struct node{
int id;
}hh[];
bool die[];
int target[];
int ans_min(),ans_max();
int in[];
int low[],dfn[],zhan[],bl[],size[];
int cnt,top,qlt;
bool vis[];
int cl[];
inline void tarjan(int u){
dfn[u]=low[u]=++cnt;
zhan[++top]=u;
vis[u]=;
for(int i=pre[u];i!=-;i=a[i].n){
int e(a[i].e);
if(!dfn[e]){
tarjan(e);
low[u]=my_min(low[u],low[e]);
}
else
if(vis[e])
low[u]=my_min(low[u],dfn[e]);
}
if(low[u]==dfn[u]){
qlt++;
while(){
int tmp(zhan[top--]);
bl[tmp]=qlt;
vis[tmp]=;
size[qlt]++;
if(tmp==u)
break;
}
}
}
inline bool cmp(node a,node b){
if(cl[bl[a.id]]==cl[bl[b.id]])
return in[a.id]<in[b.id];
return cl[bl[a.id]]<cl[bl[b.id]];
}
queue<int>q;
int now(0x7fffffff),inf(0x7fffffff),fir;
int main(){
memset(pre,-,sizeof(pre));
n=read();
for(int i=;i<=n;i++){
hh[i].id=i;
target[i]=read();
if(target[i]==i){
die[i]=;
bl[i]=++qlt;
cl[qlt]=;
size[qlt]=;
ans_max++,ans_min++;
}
}
for(int i=;i<=n;i++){
if(!die[i]&&!die[target[i]])
insert(i,target[i]),in[target[i]]++;
}
for(int i=;i<=n;i++)
if(!dfn[i]&&!die[i])
tarjan(i);
for(int i=;i<=tot;i++){
int s(a[i].s),e(a[i].e);
s=bl[s],e=bl[e];
if(s!=e)
cl[s]=cl[e]=;
}
for(int i=;i<=qlt;i++){
if(cl[i]==&&size[i]>){
ans_max+=size[i]-;
ans_min+=(size[i]+)>>;
}
}
sort(hh+,hh++n,cmp);
for(int i=;i<=n;i++){
int tmp(hh[i].id);
if(cl[bl[tmp]]==&&!in[tmp]){
now=my_min(now,i);
continue;
}
if(cl[bl[tmp]]==&&in[tmp]){
fir=i;
break;
}
}
if(now!=inf){
ans_max+=n-fir+;
for(int i=now;i<fir;i++)
q.push(hh[i].id);
while(!q.empty()){
int k(q.front());
cl[bl[k]]=;
q.pop();
int tar(target[k]);
if(!die[tar]){
die[tar]=;
cl[bl[tar]]=;
ans_min++;
int kk(target[tar]);
in[kk]--;
if(!die[kk]&&!in[kk])
q.push(kk);
}
}
}
for(int i=;i<=cnt;i++)
if(cl[i])
ans_min+=(size[i]+)>>;
printf("%d %d",ans_min,ans_max);
}
[POI2008]枪战Maf的更多相关文章
- BZOJ 1124: [POI2008]枪战Maf
1124: [POI2008]枪战Maf Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 617 Solved: 236[Submit][Status ...
- bzoj 1124 [POI2008]枪战Maf 贪心
[POI2008]枪战Maf Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 741 Solved: 295[Submit][Status][Disc ...
- 【BZOJ1124】[POI2008]枪战Maf 贪心+思路题
[BZOJ1124][POI2008]枪战Maf Description 有n个人,每个人手里有一把手枪.一开始所有人都选定一个人瞄准(有可能瞄准自己).然后他们按某个顺序开枪,且任意时刻只有一个人开 ...
- [POI2008]枪战Maf题解
问题 C: [POI2008]枪战Maf 时间限制: 1 Sec 内存限制: 256 MB 题目描述 有n个人,每个人手里有一把手枪.一开始所有人都选定一个人瞄准(有可能瞄准自己).然后他们按某个顺 ...
- BZOJ1124 [POI2008]枪战Maf[贪心(证明未完成)+拓扑排序]
吐槽:扣了几个小时,大致思路是有了,但是贪心的证明就是不会, 死磕了很长时间,不想想了,结果码代码又不会码.. 深深体会到自己码力很差,写很多行还没写对,最后别人代码全一二十行,要哭了 以下可能是个人 ...
- bzoj1124[POI2008]枪战maf
这代码快写死我了.....死人最多随便推推结论.死人最少,每个环可以单独考虑,每个环上挂着的每棵树也可以分别考虑.tarjan找出所有环,对环上每个点,求出选它和不选它时以它为根的树的最大独立集(就是 ...
- 【BZOJ】1124: [POI2008]枪战Maf
题意 \(n(n < 1000000)\)个人,每个人\(i\)指向一个人\(p_i\),如果轮到\(i\)了且他没死,则他会将\(p_i\)打死.求一种顺序,问死的人最少和最多的数目. 分析 ...
- BZOJ1124 POI2008枪战Maf(环套树+贪心)
每个点出度都为1,可以发现这张图其实是个环套树森林,树中儿子指向父亲,环上边同向. 首先自环肯定是没救的,先抬出去. 要使死亡人数最多的话,显然若一个点入度为0其不会死亡,而一个孤立的环至少会留下一个 ...
- BZOJ 1124: [POI2008]枪战Maf(构造 + 贪心)
题意 有 \(n\) 个人,每个人手里有一把手枪.一开始所有人都选定一个人瞄准(有可能瞄准自己).然后他们按某个顺序开枪,且任意时刻只有一个人开枪. 因此,对于不同的开枪顺序,最后死的人也不同. 问最 ...
随机推荐
- 如何在非 React 项目中使用 Redux
本文作者:胡子大哈 原文链接:https://scriptoj.com/topic/178/如何在非-react-项目中使用-redux 转载请注明出处,保留原文链接和作者信息. 目录 1.前言 2. ...
- yii2.0修改默认的访问控制器
- Intent解析
一.综述 intent对象是一个信息桶.它包含了接收它的组件感兴趣的信息(如:携带的动作和数据),附加Android系统感兴趣的信息(如:处理intent和启动目标Activity指令的组件的类别) ...
- 【Android Developers Training】 21. 创建一个可变动的UI
注:本文翻译自Google官方的Android Developers Training文档,译者技术一般,由于喜爱安卓而产生了翻译的念头,纯属个人兴趣爱好. 原文链接:http://developer ...
- Python3.5学习笔记-文件操作
在Python中,操作文件对象使用open函数来创建,下表列出了常用的操作file的函数: 序号 方法及描述 1.file.close() 关闭文件.关闭后文件不能再进行读写操作. 2.file.fl ...
- JAVAEE——SSH三大框架整合(spring+struts2+hibernate)
一.整合原理 二.导包(41个) 1.hibernate (1)hibernate/lib/required (2)hibernate/lib/jpa | java persist api java的 ...
- Bootstrap列表组
前面的话 列表组是Bootstrap框架新增的一个组件,可以用来制作列表清单.垂直导航等效果,也可以配合其他的组件制作出更漂亮的组件.本文将详细介绍Bootstrap列表组 基础列表组 基础列表组,看 ...
- window.onload的使用心得
如果我问你window.onload是什么意思,恐怕你会回答我:"这不是页面加载完就执行吗". 但是答案是不一定,得看你怎么用.看一下例子吧 例1: 代码如下: <! ...
- SQL语言-----数据操作
数据操作 增加数据,insert into 标准格式 insert into 表名 (字段的列表)value(数据列表): 使用set insert into 表名 set 字段1=值,2.....: ...
- CentOS7 yum安装zabbix3.2.6
前言: 本人小白,在一个多月前通过面试进入公司,在进入公司的第一天,老板把我叫到他办公室,坐下来慢慢喝茶,吹牛,给我吹他们以前做的软件,经营的产品,还装作一副什么都告诉我的样子,其实这都是套路,我早已 ...