codeforces#397D Artsem and Saunders
cf765

Artsem and Saunders - codeforces#397D

where

思考

此題目中兩個條件為:

從第一個式子,或者是將 f(x) 的 x 指向 f(x) 畫成一張有向圖,再將 h(x)、g(x) 用上面的條件加點加邊上去,會發現有 m 個點經由 h 這個函式指向 f(x),而 m 則為 f(x) 相異數的數量。

因此將 f(x) 相異數填上 h 之後,再利用第一個式子產出 g (因該式為 [n] ),由第二個式子確認即可。

Code

#include <bits/stdc++.h>
using namespace std;
int T, N, M, Q, F[100005], G[100005], H[100005], Hi[100005];
//Hi為H之inverse

void ini(void){
  M = 0;
  scanf("%d", &N);
  for(int i = 1; i <= N; i++){
    scanf("%d", F + i);
    if(!G[ F[i] ]){
    //利用目前沒在用的G來當確認重複f(x)用
      G[ F[i] ] = 1;
      
      H[ ++M ] = F[i];
      Hi[ F[i] ] = M;
    }
  }
}

int sol(void){
  int i;
  memset(G, 0, sizeof(G));
  
  //h( g(x) ) = f(x)
  for(i = 1; i <= N; i++){
    G[i] = Hi[ F[i] ];
  }
  
  //g( h(x) ) = x
  for(i = 1; i <= M; i++){
    if(G[H[i]] != i){
      printf("-1\n");
      return 0;
    }
  }
  
  //output
  printf("%d\n", M);
  for(i = 1; i <= N; i++){
    printf("%d", G[i]);
    if(i != N) printf(" ");
    else printf("\n");
  }
  for(i = 1; i <= M; i++){
    printf("%d", H[i]);
    if(i != M) printf(" ");
    else printf("\n");
  }
  return 0;
}

int main(void){
  int i, j;

  ini();

  sol();

}
*****
Written by Mi on 16 February 2017