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. Jenkins Tomcat安装设置

    Jenkins Tomcat安装设置 以下为必须满足Jenkins Tomcat设置的先决条件. 第1步:验证安装Java 要验证Java安装,打开控制台并执行以下Java命令. OS 任务 命令 W ...

  2. HP VC模块Server Profile配置快速参考(With SUS)

    以管理员身份登录VCM 准备进行Server Profiles的配置 在左侧导航栏中找到并点击"Server Profiles",在右侧主窗口的左下角点击"Add&quo ...

  3. gets函数的完美替代

    众所周知 在C语言中scanf用来读取一行字符串时遇到空格或回车会停止 而若要读入一行带空格的字符串时 有些人会用gets来代替 然而,gets的最大问题在于:会读取超过数组长度上限个字符,而超出长度 ...

  4. tendermint 跟tikv结合

    import ( "fmt" "github.com/allegro/bigcache" "github.com/kooksee/usmint/cmn ...

  5. .NET导出Excel之NPOI

    前段时间研究过微软的Excel导出.table输出Excel,而它们也存在一些弊端: 1.对于微软的Excel导出存在一些弊端,如:需要安装Office软件.速度问题: 2.table输出Excel在 ...

  6. how to update product listing price sale price and sale date using mobile App

    Greetings from Amazon Seller Support, Thank you for writing back to us. I have reviewed our previous ...

  7. scrum立会报告+燃尽图(第二周第四次)

    此作业要求参考: https://edu.cnblogs.com/campus/nenu/2018fall/homework/2249 一.小组介绍 组名:杨老师粉丝群 组长:乔静玉 组员:吴奕瑶.公 ...

  8. mysql---增删用户

    Mysql创建.删除用户 MySql中添加用户,新建数据库,用户授权,删除用户,修改密码(注意每行后边都跟个  ;  表示一个命令语句结束): 1.新建用户 登录MYSQL: @>mysql - ...

  9. 复利计算程序单元测试(C语言)

    对我们和复利计算程序,写单元测试. 有哪些场景? 期待的返回值 写测试程序. 运行测试. 我的复利计算程序是用C语言写的,不懂使用C语言的测试工具,所以用C语言的运行结果来反映测试结果. 测试模块(场 ...

  10. 《高性能JavaScript》学习笔记(2)——日更中

    我说日更就日更,接着....今天从缓冲布局信息开始啦! -------------------2016-7-22 21:09:12------------------------------- 14. ...