#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;

vector<vector<char>> mat;
vector<pair<int,string>> in;
vector<string> in2;
vector<string> in3;
vector<string> in4;
vector<string> in5;
vector<string> in6;
vector<string> in7;
vector<string> in8;
vector<string> in9;
vector<string> in10;
vector<string> in11;
vector<string> in12;
vector<string> concat_in;
int n,m;

void answer_print(){
    for(int i=0;i<n;i++){
        for(int j=0;j<n;j++){        
            cout << mat[i][j] ;
            if(j==n-1) cout << endl;
        }
    }
}

bool isPut(int x,int y,string str){
    if(mat[y][x] != '.') return false;
    if(n-x+1 < str.size()) return false;
    return true;
}

void Put(int x,int y,string str){
    for(int i = x;i<x+str.size();i++){
        mat[y][i] = str[i-x];
    }
}

void solve(){
    int k=0;

    for(int i=0;i<n;i++){
        for(int j=0;j<n;j++){
            if(isPut(j,i,concat_in[k])) {
                Put(j,i,concat_in[k]);
                k++;
            }
        }
    }
}

int main(){

    // input
    cin >> n >> m;
    mat.resize(n);in.resize(m);
    for(int i=0;i<n;i++) mat[i].resize(n,'.');

    for(int i=0;i<m;i++) {
        cin >>in[i].second;
        in[i].first = in[i].second.size();
    }

    for(int i=0;i<in.size();i++){
        switch(in[i].first){
            case 2 : in2.push_back(in[i].second);break;
            case 3 : in3.push_back(in[i].second);break;
            case 4 : in4.push_back(in[i].second);break;
            case 5 : in5.push_back(in[i].second);break;
            case 6 : in6.push_back(in[i].second);break;
            case 7 : in7.push_back(in[i].second);break;
            case 8 : in8.push_back(in[i].second);break;
            case 9 : in9.push_back(in[i].second);break;
            case 10 : in10.push_back(in[i].second);break;
            case 11 : in11.push_back(in[i].second);break;
            case 12 : in12.push_back(in[i].second);break;
            default: break;
        }
    }
    for(int i=0;i<in10.size();i++) concat_in.push_back(in10[i]);
    for(int i=0;i<in5.size();i++) concat_in.push_back(in5[i]);
    for(int i=0;i<in12.size();i++) concat_in.push_back(in12[i]);
    for(int i=0;i<in8.size();i++) concat_in.push_back(in8[i]);
    for(int i=0;i<in11.size();i++) concat_in.push_back(in11[i]);
    for(int i=0;i<in9.size();i++) concat_in.push_back(in9[i]);
    for(int i=0;i<in7.size();i++) concat_in.push_back(in7[i]);
    for(int i=0;i<in6.size();i++) concat_in.push_back(in6[i]);
    for(int i=0;i<in4.size();i++) concat_in.push_back(in4[i]);
    for(int i=0;i<in3.size();i++) concat_in.push_back(in3[i]);
    for(int i=0;i<in2.size();i++) concat_in.push_back(in2[i]);
    

    solve();
    
    answer_print();

}
#line 1 "main.cpp"
#include <algorithm>
#include <assert.h>
#include <bitset>
#include <cfloat>
#include <deque>
#include <fstream>
#include <functional>
#include <iomanip>
#include <iostream>
#include <limits.h>
#include <list>
#include <map>
#include <math.h>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <string>
#include <string.h>
#include <time.h>
#include <unordered_map>
#include <unordered_set>
#include <vector>
#define rep(i,n) for(int i=0;i<n;i++)
#define REP(i,n) for(int i=1;i<=n;i++)
#define int long long
#define ll long long
#define eps LDBL_EPSILON
#define mod (ll)1000000007
#define INF LLONG_MAX/10
#define P pair<int,int>
#define prique priority_queue
using namespace std;
int par[400010], rankh[400010], siz[400010], edge[400010];
void init(int n) {
	for (int i = 0; i <= n; i++) {
		par[i] = i;
		rankh[i] = 0;
		siz[i] = 1;
		edge[i] = 0;
	}
}
int find(int x) {
	if (par[x] == x)return x;
	else return par[x] = find(par[x]);
}
void unite(int x, int y) {
	x = find(x);
	y = find(y);
	if (x == y) {
		edge[x]++;
		return;
	}
	if (rankh[x] < rankh[y]) {
		par[x] = y;
		siz[y] += siz[x];
		edge[y] += edge[x] + 1;
	}
	else {
		par[y] = x;
		if (rankh[x] == rankh[y])rankh[x]++;
		siz[x] += siz[y];
		edge[x] += edge[y] + 1;
	}
}
bool same(int x, int y) {
	return find(x) == find(y);
}
int size(int x) {
	return siz[find(x)];
}
int edges(int x) {
	return edge[find(x)];
}
int n, a[200010], b[200010];
map<int, int> mp;
signed main() {
	cin >> n;
	rep(i, n) {
		cin >> a[i] >> b[i];
		mp[a[i]] = 0;
		mp[b[i]] = 0;
	}
	int cnt = 1;
	for (pair<const int, int>& p : mp) {
		p.second = cnt;
		cnt++;
	}
	init(mp.size());
	rep(i, n) {
		unite(mp[a[i]], mp[b[i]]);
	}
	set<int> st;
	int ans = 0;
	REP(i, mp.size()) {
		if (st.find(find(i)) != st.end())continue;
		ans += min(edges(i), size(i));
		st.insert(find(i));
	}
	cout << ans << endl;
}
