[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的更多相关文章

  1. BZOJ 1124: [POI2008]枪战Maf

    1124: [POI2008]枪战Maf Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 617  Solved: 236[Submit][Status ...

  2. bzoj 1124 [POI2008]枪战Maf 贪心

    [POI2008]枪战Maf Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 741  Solved: 295[Submit][Status][Disc ...

  3. 【BZOJ1124】[POI2008]枪战Maf 贪心+思路题

    [BZOJ1124][POI2008]枪战Maf Description 有n个人,每个人手里有一把手枪.一开始所有人都选定一个人瞄准(有可能瞄准自己).然后他们按某个顺序开枪,且任意时刻只有一个人开 ...

  4. [POI2008]枪战Maf题解

    问题 C: [POI2008]枪战Maf 时间限制: 1 Sec  内存限制: 256 MB 题目描述 有n个人,每个人手里有一把手枪.一开始所有人都选定一个人瞄准(有可能瞄准自己).然后他们按某个顺 ...

  5. BZOJ1124 [POI2008]枪战Maf[贪心(证明未完成)+拓扑排序]

    吐槽:扣了几个小时,大致思路是有了,但是贪心的证明就是不会, 死磕了很长时间,不想想了,结果码代码又不会码.. 深深体会到自己码力很差,写很多行还没写对,最后别人代码全一二十行,要哭了 以下可能是个人 ...

  6. bzoj1124[POI2008]枪战maf

    这代码快写死我了.....死人最多随便推推结论.死人最少,每个环可以单独考虑,每个环上挂着的每棵树也可以分别考虑.tarjan找出所有环,对环上每个点,求出选它和不选它时以它为根的树的最大独立集(就是 ...

  7. 【BZOJ】1124: [POI2008]枪战Maf

    题意 \(n(n < 1000000)\)个人,每个人\(i\)指向一个人\(p_i\),如果轮到\(i\)了且他没死,则他会将\(p_i\)打死.求一种顺序,问死的人最少和最多的数目. 分析 ...

  8. BZOJ1124 POI2008枪战Maf(环套树+贪心)

    每个点出度都为1,可以发现这张图其实是个环套树森林,树中儿子指向父亲,环上边同向. 首先自环肯定是没救的,先抬出去. 要使死亡人数最多的话,显然若一个点入度为0其不会死亡,而一个孤立的环至少会留下一个 ...

  9. BZOJ 1124: [POI2008]枪战Maf(构造 + 贪心)

    题意 有 \(n\) 个人,每个人手里有一把手枪.一开始所有人都选定一个人瞄准(有可能瞄准自己).然后他们按某个顺序开枪,且任意时刻只有一个人开枪. 因此,对于不同的开枪顺序,最后死的人也不同. 问最 ...

随机推荐

  1. ionic+AnjularJs实现省市县三级联动效果

    建议对ionic和AnjularJs有一定了解的人可以用到,很多时候我们要用到选择省份.城市.区县的功能,现在就跟着我来实现这个功能吧,用很少的代码(我这里是根据客户的要求,只显示想要显示的部分省份和 ...

  2. SOD开源框架MSF(消息服务框架)介绍

    前言:之前想做消息的广播,拖着就忘记了,现在拿了医生的框架来学习,就按实现了之前想实现的功能. 传送门http://www.cnblogs.com/bluedoctor/,框架的获取,按传送门的链接就 ...

  3. js返回格式化的日期(年-月-日)

    var d = new Date(); var str = d.getFullYear()+"-"+(d.getMonth()+1)+"-"+d.getDate ...

  4. Linux常用操作命令(二)

    ab命令压测: ab -n 1 -c 1 -p post.txt -T 'application/x-www-form-urlencoded' -H 'User-U:2Lh72GM2UumEAnZzM ...

  5. c# webbrower 代理 类 IEProxy

    using System;using System.Collections.Generic;using System.Linq;using System.Runtime.InteropServices ...

  6. 浅析ConcurrentHashMap

    一.导论 这些天一直在看关于多线程和高并发的书籍,也对jdk中的并发措施了解了些许,看到concurrentHashMap的时候感觉知识点很乱,有必要写篇博客整理记录一下. 当资源在多线程下共享时会产 ...

  7. String详细学习

    学这些东西,就像是扎马步.小说里郭靖学不会招数,就会扎马步.搞JS,内力还是必须要深厚,深厚,深厚. 1,stringObject.slice(start,end) slice() 方法可提取字符串的 ...

  8. OJ2237第k小数题解

    题目描述: 有n个数,请你找出第k小的数. 输入描述: 第一行有2个正整数n,k(n,k<=10^7)第二行有n个非负数ai(ai<=10^5) 输出描述: 输出第k小的数. 输入样例: ...

  9. (转载)java基础:关于java流与文件操作

    原文摘自: http://www.blogjava.net/haizhige/archive/2008/08/03/219668.html 1.描述:流是字节数据或字符数据序列. Java采用输入流对 ...

  10. jsPlumb之流程图项目总结及实例

    在使用jsPlumb过程中,所遇到的问题,以及解决方案,文中引用了<数据结构与算法JavaScript描述>的相关图片和一部分代码.截图是有点多,有时比较懒,没有太多的时间去详细的编辑. ...