Kernel Knights
题目链接:
http://acm.hust.edu.cn/vjudge/contest/127407#problem/K
Description
Jousting is a medieval contest that involves people on horseback trying to strike each other with wooden lances while riding at high speed. A total of 2n knights have entered a jousting tournament — n knights from each of the two great rival houses. Upon arrival, each knight has challenged a single knight from the other house to a duel. A kernel is defined as some subset S of knights with the following two properties: • No knight in S was challenged by another knight in S. • Every knight not in S was challenged by some knight in S. Given the set of the challenges issued, find one kernel. It is guaranteed that a kernel always exists.Input
The input file contains several test cases, each of them as described below. The first line contains an integer n (1 ≤ n ≤ 100000) — the number of knights of each house. The knights from the first house are denoted with integers 1 through n, knights from the second house with integers n + 1 through 2n. The following line contains integers f1, f2, . . ., fn — the k-th integer fk is the index of the knight challenged by knight k (n + 1 ≤ fk ≤ 2n). The following line contains integers s1, s2 , . . ., sn — the k-th integer sk is the index of the knight challenged by knight n + k (1 ≤ sk ≤ n).Output
For each case, output the indices of the knights in the kernel on a single line. If there is more than one solution, you may output any one.Sample Input
4 5 6 7 7 1 3 2 3Sample Output
1 2 4 8##题意: 有两队骑士各n人,每位骑士会挑战对方队伍的某一个位骑士. (可能相同) 要求找出一个集合S,使得:(任意满足条件即可) 集合S中的骑士不会互相挑战. 每个集合外的骑士必定会被集合S内的某个骑士挑战.
##题解: 一开始看题有点懵比,题目的两层要求绕得有点糊涂. 在模拟样例的过程中发现,有些点是必须在S中的,而有些必须在S外,有些是不固定的. 首先,如果某个骑士没有被人挑战,那么他一定要位于S中. (反之他在集合外的话,就违背了条件2). 然后,如果某个骑士被确定在S中时,那么他的挑战对象一定要在S外. (反之违背条件1). 若某个骑士i被多个人挑战,那么要先对这些挑战者逐一进行上述判断,若某个挑战者被确定在S外,那么说明能使骑士i满足条件2的挑战者少了一个(等同于少了一个挑战者). 若所有挑战者都在S外,那么i一定在S内.
一开始觉得上述条件不够充分,特别是存在多个挑战者时,考虑会不会存在某个挑战者无法确定而导致i确定不了. 考虑无法确定的情况: 首先一定是成对出现,若只出现一个,那么由上述判据一定能够确定它. 比如样例中的1<->5(互相挑战),上述判据就无法确定. 这时候可以推断1和5只要任意一个在集合S内都满足情况.
直接用dfs或bfs搜状态即可,从入度为0的点开始,若某点的父结点被确定在S外,则将该点的入度减少1.
##代码: ``` cpp #include