[POI2008]MAF-Mafia
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的更多相关文章
- BZOJ 1124: [POI2008]枪战Maf
1124: [POI2008]枪战Maf Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 617 Solved: 236[Submit][Status ...
- [POI2008]枪战Maf
[POI2008]枪战Maf 题目 有n个人,每个人手里有一把手枪.一开始所有人都选定一个人瞄准(有可能瞄准自己).然后他们按某个顺序开枪,且任意时刻只有一个人开枪.因此,对于不同的开枪顺序,最后死的 ...
- bzoj 1124 [POI2008]枪战Maf 贪心
[POI2008]枪战Maf Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 741 Solved: 295[Submit][Status][Disc ...
- 【BZOJ1124】[POI2008]枪战Maf 贪心+思路题
[BZOJ1124][POI2008]枪战Maf Description 有n个人,每个人手里有一把手枪.一开始所有人都选定一个人瞄准(有可能瞄准自己).然后他们按某个顺序开枪,且任意时刻只有一个人开 ...
- [POI2008]枪战Maf题解
问题 C: [POI2008]枪战Maf 时间限制: 1 Sec 内存限制: 256 MB 题目描述 有n个人,每个人手里有一把手枪.一开始所有人都选定一个人瞄准(有可能瞄准自己).然后他们按某个顺 ...
- BZOJ1124 [POI2008]枪战Maf[贪心(证明未完成)+拓扑排序]
吐槽:扣了几个小时,大致思路是有了,但是贪心的证明就是不会, 死磕了很长时间,不想想了,结果码代码又不会码.. 深深体会到自己码力很差,写很多行还没写对,最后别人代码全一二十行,要哭了 以下可能是个人 ...
- 枪战Maf[POI2008]
题目描述 有n个人,每个人手里有一把手枪.一开始所有人都选定一个人瞄准(有可能瞄准自己).然后他们按某个顺序开枪,且任意时刻只有一个人开枪.因此,对于不同的开枪顺序,最后死的人也不同. 输入 输入n人 ...
- bzoj1124[POI2008]枪战maf
这代码快写死我了.....死人最多随便推推结论.死人最少,每个环可以单独考虑,每个环上挂着的每棵树也可以分别考虑.tarjan找出所有环,对环上每个点,求出选它和不选它时以它为根的树的最大独立集(就是 ...
- 【BZOJ】1124: [POI2008]枪战Maf
题意 \(n(n < 1000000)\)个人,每个人\(i\)指向一个人\(p_i\),如果轮到\(i\)了且他没死,则他会将\(p_i\)打死.求一种顺序,问死的人最少和最多的数目. 分析 ...
- BZOJ1124 POI2008枪战Maf(环套树+贪心)
每个点出度都为1,可以发现这张图其实是个环套树森林,树中儿子指向父亲,环上边同向. 首先自环肯定是没救的,先抬出去. 要使死亡人数最多的话,显然若一个点入度为0其不会死亡,而一个孤立的环至少会留下一个 ...
随机推荐
- Bug 级别定义标准
缺陷种类 缺陷级别 详细说明 功能缺陷 Urgent (V级) 1.操作系统无法正常使用,死机,出现致命错误 2.数据丢失 3.被测试系统频繁崩溃,程序出错,使功能不能继续使用 4.性能与需求不一致 ...
- Mybatis利用拦截器做统一分页
mybatis利用拦截器做统一分页 查询传递Page参数,或者传递继承Page的对象参数.拦截器查询记录之后,通过改造查询sql获取总记录数.赋值Page对象,返回. 示例项目:https://git ...
- Golang项目开发管理
工具 1. task(项目管理,类似于make) go get -u -v github.com/go-task/task/cmd/task 2. gopm(go依赖管理) go get -u git ...
- [leetcode-914-X of a Kind in a Deck of Cards]
In a deck of cards, each card has an integer written on it. Return true if and only if you can choos ...
- rest_framework组件
认证组件 局部认证 在需要认证的视图类里加上authentication_classes = [认证组件1类名,认证组件2类名....] 示例如下: seralizers.py from rest_f ...
- Coloring a Tree(耐心翻译+思维)
Description You are given a rooted tree with n vertices. The vertices are numbered from 1 to n, the ...
- 寻找bug
bug1:void不应有返回值. bug2:while(n--)没有条件终止循环. bug3:size和data没有定义 bug4:arr 是sz 在大于0的情况下创建的 一定部位bull 下面的 ...
- 【Alpha】阶段第一次Scrum Meeting
[Alpha]阶段第一次Scrum Meeting 工作情况 团队成员 今日已完成任务 明日待完成任务 刘峻辰 后端接口开发 测试接口,修正bug 赵智源 撰写测试方案书 部署实际任务和编写测试样例 ...
- 随机生成四则运算式2-NEW+PSP项目计划(补充没有真分数的情况)
PS:这是昨天编写的随机生成四则运算式2的代码:http://www.cnblogs.com/wsqJohn/p/5264448.html 做了一些改进. 补:在上一次的运行中并没有加入真分数参与的运 ...
- OpenCV学习笔记——腐蚀与膨胀
1.膨胀 此操作将图像 与任意形状的内核 (),通常为正方形或圆形,进行卷积. 内核 有一个可定义的 锚点, 通常定义为内核中心点. 进行膨胀操作时,将内核 划过图像,将内核 覆盖区域的最大相素值提取 ...