1124: [POI2008]枪战Maf

Time Limit: 10 Sec  Memory Limit: 162 MB
Submit: 659  Solved: 259
[Submit][Status][Discuss]

Description

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

Input

输入n人数<1000000 每个人的aim

Output

你要求最后死亡数目的最小和最大可能

Sample Input

8
2 3 2 2 6 7 8 5

Sample Output

3 5

不看数据范围可能看起来像是缩点树归的样子, 但是平常的 $O(n^2)$ 树归在这里显然需要 $\text{真-}Owys$ 才能过( $\text{-}Owys$大法好, $n^2$ 过 $5 \times 10^5$ )(雾

然后按照图论题的一般套路就该找规律了w(找不到规律就成了神tm不可做题了)

经过一波 $Tarjan$ 缩点后再YY我们可以得到以下结论:

首先对于最大死亡数来说:

当 $SCC$ 为一个点的最大死亡数在存在入边时为$1$, 否则为 $0$.

当 $SCC$ 为一个环的最大死亡数在存在入边时为 $SCC$ 中的结点数 $size$ , 否则为 $size-1$ (有一个点是无法杀死的)

当环存在入边时还要加上连入的环的结点数再减去其中的零入度结点(因为零入度结点不可能死亡).

然后是最小死亡数:

首先零入度结点必定无法杀死, 而零入度结点的目标必死. 所以我们可以在预处理时将零入度结点压入一个队列, 然后删除它和它的目标, 更新答案, 并将删掉的结点的目标的入度减去 $1$ . 因为杀死必死的人后可能它的目标的入度变成 $0$ 然后变成新的存活结点. 新的存活结点入队. 如此处理直至队列为空.

然后我们可以发现所有的链都会在这个过程中被处理掉, 也就是说图里应该删得只剩下几坨环了. 然后这时我们可以发现对于环来说, 若环中结点数为 $s$ , 则至少要死去 $\left \lceil \frac {s}{2} \right \rceil$ 个结点. (每次刚好隔开杀手, 隔一个死一个w)

如此处理即可求出最终解.

辣鸡分类讨论吃枣药丸(╯‵□′)╯︵┻━┻(雾

参考代码

GitHub

 #include <stack>
#include <queue>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm> const int MAXN=; int n;
int scc;
int Time;
int maxA;
int minA;
int dfn[MAXN];
int low[MAXN];
int size[MAXN];
int belong[MAXN];
int target[MAXN];
int inDegree[MAXN];
int inDegreeSCC[MAXN]; bool visited[MAXN]; std::stack<int> s; void Initialize();
void DFS(int); int main(){
std::queue<int> live;
Initialize();
for(int i=;i<=n;i++){
if(inDegree[i]==)
live.push(i);
}
while(!live.empty()){
int top=live.front();
live.pop();
visited[top]=true;
if(visited[target[top]])
continue;
minA++;
visited[target[top]]=true;
if((--inDegree[target[target[top]]])==&&!visited[target[target[top]]])
live.push(target[target[top]]);
}
for(int i=;i<=n;i++){
int cnt=;
if(!visited[i]){
int x=i;
do{
visited[x]=true;
cnt++;
x=target[x];
}while(x!=i);
}
if(cnt>)
minA+=(cnt+)/;
}
memset(visited,,sizeof(visited));
for(int i=;i<=n;i++){
if(dfn[i]==)
DFS(i);
}
for(int i=;i<=n;i++){
if(target[i]==i||belong[i]!=belong[target[i]])
inDegreeSCC[belong[target[i]]]++;
}
for(int i=;i<=scc;i++){
if(inDegreeSCC[i]>)
maxA+=size[i];
else
maxA+=size[i]-;
}
printf("%d %d\n",minA,maxA);
return ;
} void DFS(int root){
dfn[root]=low[root]=++Time;
visited[root]=true;
s.push(root);
if(visited[target[root]]){
low[root]=std::min(low[root],dfn[target[root]]);
}
else if(dfn[target[root]]==){
DFS(target[root]);
low[root]=std::min(low[root],low[target[root]]);
}
if(low[root]==dfn[root]){
scc++;
int top;
do{
top=s.top();
belong[top]=scc;
size[scc]++;
visited[top]=false;
s.pop();
}while(top!=root);
}
} inline void Initialize(){
scanf("%d",&n);
for(int i=;i<=n;i++){
scanf("%d",target+i);
inDegree[target[i]]++;
}
}

Backup

[BZOJ 1124][POI 2008] 枪战 Maf的更多相关文章

  1. 【BZOJ 1124】[POI2008] 枪战Maf Tarjan+树dp

    #define int long long using namespace std; signed main(){ 这个题一看就是图论题,然后我们观察他的性质,因为一个图论题如果没有什么性质,就是真· ...

  2. bzoj 1112 poi 2008 砖块

    这滞胀题调了两天了... 好愚蠢的错误啊... 其实这道题思维比较简单,就是利用treap进行维护(有人说线段树好写,表示treap真心很模板) 就是枚举所有长度为k的区间,查出中位数,计算代价即可. ...

  3. BZOJ 1124: [POI2008]枪战Maf

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

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

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

  5. [POI2008]枪战Maf

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

  6. [BZOJ 1013][JSOI 2008] 球形空间产生器sphere 题解(高斯消元)

    [BZOJ 1013][JSOI 2008] 球形空间产生器sphere Description 有一个球形空间产生器能够在n维空间中产生一个坚硬的球体.现在,你被困在了这个n维球体中,你只知道球 面 ...

  7. [POI 2008&洛谷P3467]PLA-Postering 题解(单调栈)

    [POI 2008&洛谷P3467]PLA-Postering Description Byteburg市东边的建筑都是以旧结构形式建造的:建筑互相紧挨着,之间没有空间.它们共同形成了一条长长 ...

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

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

  9. [POI2008]枪战Maf题解

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

随机推荐

  1. docker中的命令参数(小白常用)

    1 docker run run是最常用的命令,他是docker creat和docker start命令的组合,创建容器并启动它.run的参数比较难理解的是-i 和-t 以及-d,分别说说这三个. ...

  2. k8s中secret解析

    概览 Secret是用来保存小片敏感数据的k8s资源,例如密码,token,或者秘钥.这类数据当然也可以存放在Pod或者镜像中,但是放在Secret中是为了更方便的控制如何使用数据,并减少暴露的风险. ...

  3. webbrowser控件使用时的注意事项

    如果HtmlElement内的没有信息,则HtmlElement的OuterText属性值为null:OuterHtml属性值则为相应的html值 如果使用OuterText属性,使用前要判断下.

  4. WPF 小知识点001

    1.DataGrid 单选事件 <DataGrid MinHeight="150"                  AutoGenerateColumns="Fa ...

  5. Grid控件

    Grid控件是WPF布局容器中功能最强大.最灵活的控件.Grid控件基本上能够完成其他WPF容器控件所能完成的功能,Microsoft建议大多数界面的布局都使用Grid控件来实现,因此默认情况下.vs ...

  6. c#项目代码风格要求

    代码风格没有正确与否,重要的是整齐划一,这是我拟的一份<.Net 项目代码风格要求>,供大家参考. 1. C# 代码风格要求 1.1注释 类型.属性.事件.方法.方法参数,根据需要添加注释 ...

  7. 常见IT英语单词

    lable标签,master精通.主人,reference参考,release发布,schema模式,component组件,persistence持久化,generate生成产生,plugin插件, ...

  8. hdu 1397 (素数判定)

    一开始提交了这个,果断TLE #include <cstdio> #include <iostream> #include <string> #include &l ...

  9. Bash拾遗:变量

    使用引号包裹变量 在<高级Bash脚本编程指南>中的4.1节中有这么个例子: hello="A B C D" echo $hello # A B C D echo &q ...

  10. Asp.Net实现在线网站安装(上)

    在很多年前,笔者在使用z-blog搭建个人部落格的时候,最大的感受就是z-blog在线安装功能! 因为在那个时候,以几K每秒的速度上传一个几M或者十几M的压缩包到虚拟主机上,是一个很痛苦的事情.特别是 ...