P4355 [CERC2015] Kernel Knights

P4355 [CERC2015] Kernel Knights

Title translation:

Riding is a medieval game in which people on horseback try to attack each other with wooden spears while riding at high speed. A total of 2n knights compete in a Guild Wars tournament - N knights from the two main competitors. Upon arrival, each knight challenges a knight from another room to a duel.

Kernels are defined as some subset of knights with the following two properties:

• No knight in S is challenged by another knight in S.

Every knight not in S is challenged by some knights in S.

Given the set of challenges faced, identify a kernel. The kernel is guaranteed to always exist.

Title 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 format:

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 $f_1$, $f_2$,..., $f_n$ – the k-th integer fk is the index of the knight challenged by knight k $(n+1≤ f_k ≤2n)$. 

The following line contains integers $s_1$,$s_2$,...,$s_n$ – the k-th integer sk is the index of the knight challenged by knight n+k $(1≤s_k ≤n)$.

Output format:

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.

The format check of SPJ is relatively strict, please output a space after each number, and please do not output any symbols after the last space output.

Example #1

Sample Input #1

```

5 6 7 7 
1 3 2 3
```

Sample output #1

```
1 2 4 8
```

hint:

Central Europe Regional Contest 2015 Problem K

Ideas:

Since the original graph is a bipartite graph, all cycles are even cycles.

Since each point has only one out-degree, all rings are simple rings.

Then this graph can be imagined as an inward base ring forest.

Color the nodes with degree 0 each time.

Every time a point is traversed:

- If the degree of the point to be reached is 0 or its color is not optional (because this point is not optional, it cannot be colored casually), then continue traversing.

Then do all the unmarked rings again.

Full code:

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#define maxn 500010
using namespace std;
int n;
int to[maxn], h[maxn], cnt, deg[maxn], col[maxn];
void add(int u, int v){to[u] = v, deg[v] ++;}
 
void BFS(int u){
    col[u] = 2;
    while(true){
        if(col[to[u]])break;
        deg[to[u]] --;
        if(deg[to[u]] == 0 || col[u] == 2){
            col[to[u]] = col[u] ^ 1;
            u = to[u];
        }
        else break;
    }
}
 
void Col(int u){
    col[u] = 2;
    while(true){
        if(col[to[u]])break;
        col[to[u]] = col[u] ^ 1;
        u = to[u];
    }
}
 
int main(){
    scanf("%d", &n);
    int v;
    for(int i = 1; i <= n; i ++)
        scanf("%d", &v), add(i, v);
 
    for(int i = n + 1; i <= n * 2; i ++)
        scanf("%d", &v), add(i, v);
    n <<= 1;
    for(int i = 1; i <= n; i ++)
        if(!deg[i] && !col[i])BFS(i);
    for(int i = 1; i <= n; i ++)
        if(!col[i])Col(i);
    for(int i = 1; i <= n; i ++)
        if(col[i] == 2)printf("%d ", i);
    return 0;
}

Topic link:

[CERC2015] Kernel Knights - Luogu https://www.luogu.com.cn/problem/P4355 

Guess you like

Origin blog.csdn.net/wo_ai_luo_/article/details/131471224