[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. python 标准库 -- configparser

    configparser 用于处理 ini 格式的配置文件, 其本质上是利用 open 来操作文件. 示例文件 : [zhangsan] name = zhangsan age = 12 job = ...

  2. salesforce零基础学习(七十三)ProcessInstanceWorkItem/ProcessInstanceStep/ProcessInstanceHistory浅谈

    对于审批流中,通过apex代码进行审批操作一般都需要获取当前记录对应的ProcessInstanceWorkitem或者ProcessInstanceStep然后执行Approval.process操 ...

  3. 关于MATLAB处理大数据坐标文件2017622

    今天新提交了一次数据,总量达到10337个,本以为成绩会突飞猛进,没想到还是不如从前 但是已经找到人工鼠标轨迹的程序,有待完善,接下来兵分四路:找特征.决策树.完善人工轨迹程序,使其可以将生成的数据自 ...

  4. android网页分享到朋友圈问题求助?

    目前想要实现通过QQ将网页分享到微信好友或朋友圈,看见有些APP是直接分享出去左下角图标显示的是QQ.求助各位大牛提供下思路. 这种功能是怎么实现的.应该不是通过android的系统分享实现的吧?.查 ...

  5. 【JavaScript学习】-JS内置对象2-Data对象

    Date对象: Data对象可以储存任意一个日期,并且可以精确到毫秒数(1/1000 秒). 定义: //默认初始值定义: var dataName=new Date(); /*使用关键字new;Da ...

  6. java架构师负载均衡、高并发、nginx优化、tomcat集群、异步性能优化、Dubbo分布式、Redis持久化、ActiveMQ中间件、Netty互联网、spring大型分布式项目实战视频教程百度网盘

    15套Java架构师详情 * { font-family: "Microsoft YaHei" !important } h1 { background-color: #006; ...

  7. linux服务器查看redis版本:

    linux服务器查看redis版本:redis-server-v

  8. php根据经纬度获取城市名

    /*php根据经纬度获取城市名*/ function get_my_addr_infos(){ $ch = curl_init(); $timeout = 5; $lat = $list['info' ...

  9. 【Android Developers Training】 60. 在你的UI中显示位图

    注:本文翻译自Google官方的Android Developers Training文档,译者技术一般,由于喜爱安卓而产生了翻译的念头,纯属个人兴趣爱好. 原文链接:http://developer ...

  10. JavaScript 语言基础

    js语言基础 一 基本知识 UniCode编码 区分大小写(HTML不区分/XHTML区分) Unicode转义序列 \uxxxx (\u加4位16进制表示) 注释 单行注释:// 多行注释:/* * ...