#include<bits/stdc++.h> //Ithea Myse Valgulious
namespace chtholly{
typedef long long ll;
#define re0 register int
#define rel register ll
#define rec register char
#define gc getchar
//#define gc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<23,stdin),p1==p2)?-1:*p1++)
#define pc putchar
#define p32 pc(' ')
#define pl puts("")
/*By Citrus*/
char buf[1<<23],*p1=buf,*p2=buf;
inline int read(){
  int x=0,f=1;char c=gc();
  for (;!isdigit(c);c=gc()) f^=c=='-';
  for (;isdigit(c);c=gc()) x=(x<<3)+(x<<1)+(c^'0');
  return f?x:-x;
  }
template <typename mitsuha>
inline bool read(mitsuha &x){
  x=0;int f=1;char c=gc();
  for (;!isdigit(c)&&~c;c=gc()) f^=c=='-';
  if (!~c) return 0;
  for (;isdigit(c);c=gc()) x=(x<<3)+(x<<1)+(c^'0');
  return x=f?x:-x,1;
  }
template <typename mitsuha>
inline int write(mitsuha x){
  if (!x) return 0&pc(48);
  if (x<0) pc('-'),x=-x;
  int bit[20],i,p=0;
  for (;x;x/=10) bit[++p]=x%10;
  for (i=p;i;--i) pc(bit[i]+48);
  return 0;
  }
inline char fuhao(){
  char c=gc();
  for (;isspace(c);c=gc());
  return c;
  }
}using namespace chtholly;
using namespace std;
const int yuzu=4e5;
typedef int fuko[yuzu|10];
fuko fa,sz;
struct dsu {  
  int find(int x) {
    return fa[x]?fa[x]=find(fa[x]):x;
  }
  int mg(int u,int v) {
    u=find(u),v=find(v);
    if (sz[u]&&sz[v]) return 0;
    u^v?fa[u]=v,sz[v]|=sz[u]:sz[u]=1;
    return 1;
  }
}zw;
int main() {
  int n,i,a,b,lxy=0;
  read(n);
  for (i=1;i<=n;++i) lxy+=zw.mg(read(),read());
  printf("%d\n",lxy);
}
//#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <iostream>
#include <queue>
#include <algorithm>
#include <sstream>
#include <vector>
#include <math.h>
#include <set>
#include <map>
#include <unordered_map>
#include <numeric>
#include <bitset>
#include <iomanip>
#include <cctype>
#include <cstdlib>      // srand,rand
#include <random>
#include <functional>
#include <list>
#include <stack>
#include <time.h>

#define height 50
#define width 50
#define tile_sum 2500


using namespace std;
#define ll long long
#define ll128 long long
#define lp(i,n) for(ll i=0;i<n;i++)

clock_t start_clock = clock();
clock_t end_clock = clock();

int start_x;
int start_y;

int tile[height][width];
int point[height][width];
int ans_score=0;

string direction_str;
string ans_string;

int GetTileKind(int y,int x){
    return tile[y][x];
}

void Input(){
    cin>>start_y;
    cin>>start_x;
    for(int h=0;h<height;h++){
        for(int w=0;w<width;w++){
            cin>>tile[h][w];
        }
    }
    for(int h=0;h<height;h++){
        for(int w=0;w<width;w++){
            cin>>point[h][w];
        }
    }
}

int CheckScore(string direction_str){
    int now_x=start_x;
    int now_y=start_y;
    int score=point[now_y][now_x];
    for(int i=0;i<direction_str.size();i++){
        if(direction_str[i]=='U')now_y--;
        if(direction_str[i]=='D')now_y++;
        if(direction_str[i]=='L')now_x--;
        if(direction_str[i]=='R')now_x++;
        score+=point[now_y][now_x];
    }
    return score;
}

bool CheckCanGo(int y,int x,bool gone[tile_sum]){
    if(y<0 || height<=y || x<0 || width<=x)return false;
    if(gone[GetTileKind(y,x)]==true)return false;
    return true;
}

string DicidePath(string direction_str){
    bool gone[tile_sum]={};
    int now_x=start_x;
    int now_y=start_y;
    gone[GetTileKind(now_y ,now_x )]=true;
    for(int i=0;i<direction_str.size();i++){//元々決められていたパスの処理
        if(direction_str[i]=='U')now_y--;
        if(direction_str[i]=='D')now_y++;
        if(direction_str[i]=='L')now_x--;
        if(direction_str[i]=='R')now_x++;
        gone[GetTileKind(now_y ,now_x )]=true;
    }
    char pre_direct_x='a';
    char pre_direct_y='a';
    while(true){//追加のパスを決める処理
        string CanGoDirection="";
        if(CheckCanGo(now_y - 1 ,now_x ,gone )==true){
            for(int i=0;i<now_y;i++)CanGoDirection+="U";
        }
        if(CheckCanGo(now_y + 1 ,now_x ,gone )==true){
            for(int i=0;i<49-now_y;i++)CanGoDirection+="D";
        }
        if(CheckCanGo(now_y ,now_x - 1 ,gone )==true){
            for(int i=0;i<now_x;i++)CanGoDirection+="L";
        }
        if(CheckCanGo(now_y ,now_x + 1 ,gone )==true){
            for(int i=0;i<49-now_x;i++)CanGoDirection+="R";
        }
        if(CanGoDirection.empty())break;
        direction_str+=CanGoDirection[rand()%CanGoDirection.size()];
        if(direction_str.back()=='U')now_y--;
        if(direction_str.back()=='D')now_y++;
        if(direction_str.back()=='L')now_x--;
        if(direction_str.back()=='R')now_x++;
        gone[GetTileKind(now_y ,now_x )]=true;
    }
    return direction_str;
}


int main(){
    srand((unsigned int)time(NULL));
    Input();
    direction_str.clear();
    ans_string=DicidePath(direction_str);
    ans_score=CheckScore(ans_string);
    while(true){
        end_clock = clock();
		double tt = (double)((end_clock - start_clock));
		if (tt >= (double)1800.000)break;
        int used_c_num=rand()%ans_string.size();
        direction_str.clear();
        for(int j=0;j<used_c_num;j++)direction_str+=ans_string[j];
        string now_direct_str=DicidePath(direction_str);
        int score=CheckScore(now_direct_str);
        if(ans_score<=score){
            ans_string=now_direct_str;
            ans_score=score;
        }
    }
    cout<<ans_string<<endl;
    return 0;
}
