P4355 [CERC2015] Kernel Knights
P4355 [CERC2015] Kernel Knights
题目描述
马上长矛比武是一种中世纪的比赛,参赛者骑在马上,用木制长矛高速冲刺,试图击中对方。共有 2n 名骑士参加了马上长矛比武比赛——来自两个伟大敌对家族的 n 名骑士。到达后,每位骑士向另一家族的一名骑士发起了挑战。
一个“核”被定义为骑士的某个子集 S,具有以下两个特性:
- S 中没有骑士被 S 中的其他骑士挑战。
- 不在 S 中的每个骑士都被 S 中的某个骑士挑战。
给定发出的挑战集,找到一个“核”。保证“核”总是存在。
输入格式
第一行包含一个整数 n (1 ≤ n ≤ 100000)——每个家族的骑士数量。第一个家族的骑士用整数 1 到 n 表示,第二个家族的骑士用整数 n+1 到 2n 表示。
接下来的行包含整数 \(f_1\), \(f_2\),..., \(f_n\)——第 k 个整数 \(f_k\) 是骑士 k 挑战的骑士的编号 \((n+1 ≤ f_k ≤ 2n)\)。
接下来的行包含整数 \(s_1\),\(s_2\),...,\(s_n\)——第 k 个整数 \(s_k\) 是骑士 n+k 挑战的骑士的编号 \((1 ≤ s_k ≤ n)\)。
输出格式
在一行中输出“核”中的骑士编号。如果有多个解,你可以输出其中任何一个。
SPJ 的格式校验较为严格,请在每个数字后面都输出一个空格,且在最后一个空格输出后请不要输出任何符号。
输入输出样例 #1
输入 #1
4
5 6 7 7
1 3 2 3
输出 #1
1 2 4 8
说明/提示
Central Europe Regional Contest 2015 Problem K。
题面翻译由 ChatGPT-4o 提供。
题意:
寻找集合 \(S\) ,使得:
- \(S\) 中的骑士不能互相挑战。
- 不在 \(S\) 中的骑士都会被 \(S\) 中的骑士挑战。
思路:
首先看一下挑战的具体规则:
在第 \(i\) 个位置上的数 \(k_i\) 代表着编号为 \(i\) 的骑士挑战编号为 \(k_i\) 的骑士。
观察第二条要求,不难发现,在 \(S\) 外的骑士一定都被挑战了,由此我们可以知道,只要一个骑士 \(a\) 并没有被挑战过,那么他一定在集合 \(S\) 中。
同时,因为集合内的骑士不能互相攻击,所以被骑士 \(a\) 挑战的那名骑士 \(b\) 一定在集合 \(S\) 的外面。
最后,队伍中可能出现一个非常招仇恨的骑士,他会被挑战很多次,这个时候我们只用把他排出集合 \(S\) 一次就好了(要是祂被打一次赶祂一次岂不是给人家发配边疆了)。
这时候,可能有严谨的小伙伴要问了:
那集合外面的骑士的攻击怎么办呢?
事实上,集合外的攻击完全不用管,我们只需要看好集合内的骑士让他们不要打架就可以了,至于那些被流放到集合外的骑士就不属于我们的管理范围了~。
实现:
由于要进行踢出集合和加入集合两种操作,不难想到,我们可以开一个桶标记被攻击次数,并使用队列维护此集合:
- 先把没有被攻击过的骑士加入队列。
- 进行完第一步后,把队列外没有被队列内骑士攻击的都加入队列。
然后就可以愉快的通过啦!(估计不会有人和我一样傻傻忘记输出空格全似了吧)。
AC Code:
#include<bits/stdc++.h>
using namespace std;
const int N=2e5+5;
int n,a[N],b[N],c[N];
queue<int>q;
int main(){
while(cin>>n){
memset(b,0,sizeof(b));//多测不清空
memset(c,0,sizeof(c));//亲人两行泪
int m=n*2;
for(int i=1;i<=m;i++){
cin>>a[i];
b[a[i]]++;//开桶标记被攻击次数
}
for(int i=1;i<=m;i++){
if(!b[i]){
q.push(i);//先处理没被打过的,一定在集合里
}
}
while(!q.empty()){//处理操作 2
int p=q.front();
q.pop();
c[p]=1;
if(c[a[p]])continue;//不要发配边疆,只踢出一次,方便又快捷
c[a[p]]=-1;b[a[a[p]]]--;//集合外面的骑士自己一边玩去
if(b[a[a[p]]]==0)q.push(a[a[p]]);//没人打的骑士也进来
}
for(int i=1;i<=m;i++){
if(i<=n&&c[i]>=0||i>n&&c[i]==1)cout<<i<<" ";
}
//注意输出格式 qwq
cout<<'\n';
}
return 0;//华丽结束
}
说句闲话,研究骑士的最好方式是……

浙公网安备 33010602011771号