Description

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

Input

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

Solution

其实就是一个基环树森林

显然可以把每个基环树分开,然后分情况讨论。

环:死最多:len-1,死最少:[len/2]上取整

自环:最多最少都是1

树:死最多:只剩下叶子。死最少:叶子不会死,然后父亲一定死,就贪心地让父亲就别打死爷爷。这样一定不会更劣。大概就是隔一层打一层

基环树:死最多:只剩下叶子。死最少:先把每个子树按照树的打法打完,然后基环可能会变成若干个链,每个链都是:len/2下取整。剩环的话,那么和环(或者自环)一样。

树和基环树的叶子往上打就是拓扑排序。

代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=+;
int n;
struct node{
int nxt,to;
}e[*N];
int hd[N],cnt=;
int du[N];//you xiang
int huan;//len of huan
bool on[N];//on the huan
bool vis[N];
bool die[N];
bool go[N];
bool has[N];
int to[N];
int mxans,mians;
void add(int x,int y){
e[++cnt].nxt=hd[x];
e[cnt].to=y;
hd[x]=cnt;
}
bool fl;
int sta[N],top;
vector<int>mem;
int in[N];//in the sta
void dfs(int x,int in_edge){
// cout<<" dfs "<<x<<" "<<endl;
sta[++top]=x;
vis[x]=;in[x]=;
mem.push_back(x);
for(int i=hd[x];i;i=e[i].nxt){
int y=e[i].to;
if(i==(in_edge^)) continue;
if(vis[y]){
if(in[y]&&!fl){
// cout<<" fin "<<y<<endl;
fl=true;
int z;//=sta[top];
do{
z=sta[top];
on[z]=;in[z]=;
huan++;
top--;
}while(z!=y);
}
}
else dfs(y,i);
}
if(sta[top]==x) in[x]=,top--;
}
int q[N],l,r;
int len;//len of lian
void wrk(int x,int pre){//dfs on the huan
go[x]=;
//cout<<x<<" "<<pre<<endl;
for(int i=hd[x];i;i=e[i].nxt){
int y=e[i].to;
if(y==pre) continue;
if(go[y]) continue;
if(on[y]){
//cout<<" y "<<y<<endl;
if(die[y]){
mians+=len/;len=;
}else len++;
wrk(y,x);
}
}
}
void topo(){
len=;
l=,r=;
//cout<<" huan "<<huan<<endl;
//cout<<" mem "<<mem.size()<<endl;
///cout<<mians<<endl;
for(int i=0;i<mem.size();i++){
int id=mem[i];
//cout<<id<<" "<<on[id]<<" "<<in[id]<<endl;
if(du[id]==) q[++r]=id,has[id]=;
}
if(huan==||huan>) mxans+=mem.size()-max(r,);
else mxans+=mem.size()-r;
bool kil=false;
int st;
while(l<=r){
int x=q[l++];
//cout<<" x "<<x<<endl;
//if(has[to[x]]) continue;
if(!die[x]){
if(!die[to[x]]) mians++,die[to[x]]=;
if(on[to[x]])kil=,st=to[x];
}
du[to[x]]--;
if(du[to[x]]==){
q[++r]=to[x];
}
}
if(kil){
//cout<<" kil "<<st<<endl;
//cout<<mians<<endl;
wrk(st,);
//cout<<" len "<<len<<endl;
mians+=len/;
}
else{
mians+=huan-(huan/);
}
} int main(){
scanf("%d",&n);int y;
for(int i=;i<=n;i++){
scanf("%d",&y);to[i]=y;
add(i,y);add(y,i);du[y]++;
}
for(int i=;i<=n;i++){
if(!vis[i]){
//cout<<" another "<<i<<endl;
fl=false;
huan=;
mem.clear();
dfs(i,);
topo();
//cout<<" mians "<<mians<<" mxans "<<mxans<<endl;
}
}
cout<<mians<<" "<<mxans<<endl;
return ;
} /*
Author: *Miracle*
Date: 2018/10/14 19:28:35
*/

[POI2008]MAF-Mafia的更多相关文章

  1. BZOJ 1124: [POI2008]枪战Maf

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

  2. [POI2008]枪战Maf

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

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

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

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

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

  5. [POI2008]枪战Maf题解

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

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

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

  7. 枪战Maf[POI2008]

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

  8. bzoj1124[POI2008]枪战maf

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

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

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

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

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

随机推荐

  1. C语言的函数调用过程(栈帧的创建与销毁)

    从汇编的角度解析函数调用过程 看看下面这个简单函数的调用过程: int Add(int x,int y) { ; sum = x + y; return sum; } int main () { ; ...

  2. HTTP简单教程

    目录 HTTP简介 HTTP工作原理 HTTP消息结构 客户端请求消息 服务器响应消息 实例 HTTP请求方法 HTTP响应头信息 HTTP状态码 HTTP状态码分类 HTTP状态码列表 HTTP c ...

  3. TensorFlow深度学习实战---MNIST数字识别问题

    1.滑动平均模型: 用途:用于控制变量的更新幅度,使得模型在训练初期参数更新较快,在接近最优值处参数更新较慢,幅度较小 方式:主要通过不断更新衰减率来控制变量的更新幅度. 衰减率计算公式 : deca ...

  4. 大O算法

    大O计法:根据执行次数计算#sum = (1+n)*n/2://执行了一次,即为O(1)#for(i=0;i<n;i++);//执行了n次,即为O(n)#算法的时间复杂度:T(n) = O(f( ...

  5. Docker虚拟机172.17网段冲突,导致网络访问问题

    在虚拟机中安装docker,linux ubuntu16 ,安装完公司172.17网段被docker0覆盖,导致ssh无法连接到ubuntu. 经过官网的这篇build your own bridge ...

  6. python-redis集合模式

    无序集合SADD set集合是直接去重的,只会输出 xiao hehe sadd  names3  xiao xiao hehe  hehe 获取集合 names3的所有值,集合不能用切片形式获取值, ...

  7. Fast R-CNN学习总结

    Fast R-CNN是R-CNN的改良版,同时也吸取了SPP-net中的方法.在此做一下总结. 论文中讲到在训练阶段,训练一个深度目标检测网络(VGG16),训练速度要比R-CNN快9倍左右,比SPP ...

  8. 互评Alpha版本——基于NABCD评论作品,及改进建议

    组名:可以低头,但没必要 组长:付佳 组员:张俊余  李文涛  孙赛佳  田良  于洋  刘欣  段晓睿 一.杨老师粉丝群--<弹球学成语> 1.1 NABCD分析   N(Need,需求 ...

  9. Scrum立会报告+燃尽图(十月十四日总第五次):前期宣传工作进行中

    此作业要求参见:https://edu.cnblogs.com/campus/nenu/2018fall/homework/2195 Scrum立会master:段晓睿 一.小组介绍 组长:付佳 组员 ...

  10. 图论---POJ 3660 floyd 算法(模板题)

    是一道floyd变形的题目.题目让确定有几个人的位置是确定的,如果一个点有x个点能到达此点,从该点出发能到达y个点,若x+y=n-1,则该点的位置是确定的.用floyd算发出每两个点之间的距离,最后统 ...