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. 在ViewDidLoad中往导航栈推ViewController报错

     Unbalanced calls to begin/end appearance transitions for <YZPMainViewController: 0x7fa04b4970f0& ...

  2. 手把手教你使用 VuePress 搭建个人博客

    手把手教你使用 VuePress 搭建个人博客 有阅读障碍的同学,可以跳过第一至四节,下载我写好的工具包: git clone https://github.com/zhangyunchencc/vu ...

  3. 【AngularJs】---JSONP跨域访问数据传输(JSON_CALLBACK)

    大家会自然想到只有一个字母之差的JSON吧~ JSON(JavaScript Object Notation)和JSONP(JSON with Padding)虽然只有一个字母的差别,但其实他们根本不 ...

  4. WPF几种渐变色

      [LinearGradientBrush-- 主要属性: StartPoint 获取或设置线性渐变的二维起始坐标. EndPoint 获取或设置线性渐变的二维终止坐标. 例子: <Linea ...

  5. array(1) { [0]=> int(5) }和array(1) { [0]=> string(1) "5" }

    php array数组: $arrayValue = array(5); $arrayValue = array('5'); 的不同之处 一个是整型一个是字符串型 array(1) { [0]=> ...

  6. SpringMVC笔记:annotation注解式开发

    一.配置式开发 在我们之前的学习中,springmvc使用配置式开发模式,需要在核心配置文件中springmvc.xml注册大量的bean来注入controller控制器,工作繁琐容易出错,下面我们学 ...

  7. JAVA工具系列之——Postman

    1 概述 Postman是一款测试rest接口的工具,可以实现前端未实施的情况下,后端同步开发.本文从部署到运用进行展开描写. 2 部署 第一步:进入Postman官网下载最新版本,下载链接 第二步: ...

  8. 第一个Windows窗口应用程序

    学习目的 熟悉开发工具Visual C++ 6.0和MSDN 2001的使用. 应用Windows API函数, 手工编写具有最基本构成的Windows窗口应用程序(包含WinMain入口函数, 消息 ...

  9. POJ 2524(并查集)

    这道题多了一个检查是否包含所有元素 可以设一个cnt表示集合里的数量,再与外面比较 #include <cstdio> #include <iostream> #include ...

  10. xshell ssh连接linux时提示ssh服务器拒绝了密码

    用Xshell root连接时显示ssh服务器拒绝了密码,应该是应该是sshd的设置不允许root用户用密码远程登录 修改 /etc/ssh/sshd_config文件,注意,安装了openssh才会 ...