枪战(maf)
枪战(maf)
settle the dispute. Negotiations were very tense, and at one point the trigger-happy participants drew their
guns. Each participant aims at another with a pistol. Should they go on a killing spree, the shooting will go
in accordance with the following code of honour:
the participants shoot in a certain order, and at any moment at most one of them is shooting,
no shooter misses, his target dies instantly, hence he may not shoot afterwards,
everyone shoots once, provided he had not been shot before he has a chance to shoot,
no participant may change his first target of choice, even if the target is already dead (then the shot
causes no further casualties).
An undertaker watches from afar, as he usually does. After all, the mobsters have never failed to stimulate
his business. He sees potential profit in the shooting, but he would like to know tight estimations. Precisely
he would like to know the minimum and maximum possible death rate. The undertaker sees who aims at
whom, but does not know the order of shooting. You are to write a programme that determines the numbers
reads from the standard input what target each mobster has chosen,
determines the minimum and maximum number of casualties,
输入
第1行:人数 1<=n<=1,000,000
第2行:包含了n 个整数s1,s2,...,sn,si表示第i个人瞄准的目标,注意一下第i个的目标可能为i 。
输出
输出2个整数。枪战后可能的最小和最大的死亡人数。
solution
考虑贪心。
首先没有入度的点一定不会死。假设为A
那么他们瞄准的人B一定会死,而B瞄准的人可能可以不死。
于是删除B的出边,类似拓扑序,一个点如果没有入边,它就可以不死。
还剩下若干环。
环上的点最少死n/2
最多:
1.如果这个环有入边(就是它不是一个单独的环,环外可以打到环上)
那么可以全死。因为让那个被环外打的人开枪
不然会活一个人
#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<cmath>
#define maxn 1000006
using namespace std;
int n,a[maxn],in[maxn];
int q[maxn],l,r,ans1,ans2,die[maxn];//ans1 min ans2 max
int flag[maxn];
int main()
{
cin>>n;
for(int i=1;i<=n;i++){scanf("%d",&a[i]);in[a[i]]++;}
for(int i=1;i<=n;i++){
if(!in[i])q[++r]=i,ans1++;
}
for(int i=1;i<=r;i++){
int u=q[i];int v=a[u];
if(die[v])continue;
die[v]=1;
in[a[v]]--;flag[a[v]]=1;// flag=1 exist a entrance
if(!in[a[v]])q[++r]=a[v];
}
ans2=r;
for(int i=1;i<=n;i++){
if(in[i]&&!die[i]){// in the circle
int len=0,en=0;
for(int j=i;!die[j];j=a[j]){
die[j]=1;len++;
en|=flag[j];
}
if(!en&&len>1)ans1++;//can't enter
ans2+=len/2;
}
}
printf("%d %d\n",n-ans2,n-ans1);
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构