#include <iostream>
#include <cstdio>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <deque>
#include <stack>
#include <algorithm>
#include <cstring>
#include <functional>
#include <cmath>
#include <utility>
#include <cassert>
using namespace std;
#define rep(i,n) for(int i=0;i<(n);++i)
#define rep1(i,n) for(int i=1;i<=(n);++i)
#define all(c) (c).begin(),(c).end()
#define fs first
#define sc second
#define pb push_back
#define show(x) cout << #x << " " << x << endl
typedef vector<int> vi;
typedef pair<vi,int> P;
struct edge {
	int to,cap;
	vi cost;
	int rev;
	edge(int to,int cap,vi cost,int rev):to(to),cap(cap),cost(cost),rev(rev){}
};
const int MAX_V=102;
int V;
vector<edge> G[MAX_V];
vi h[MAX_V];
vi dist[MAX_V];
int prevv[MAX_V],preve[MAX_V];
vi zero(52,0),mx(52,53),vinf(52,200);
vi operator +(const vi &l,const vi &r){
	vi ret=l;
	rep(i,52) ret[i]+=r[i];
	return ret;
}
vi operator -(const vi &l,const vi &r){
	vi ret=l;
	rep(i,52) ret[i]-=r[i];
	return ret;
}
vi operator*(const int &l,const vi &r){
	vi ret=r;
	rep(i,52) ret[i]+=l;
	return ret;
}
vi operator -(const vi &l){
	vi ret=l;
	rep(i,52) ret[i]=-ret[i];
	return ret;
}
void add_edge(int from, int to, int cap, vi cost){
	edge e1=edge(to,cap,cost,G[to].size()),e2(from,0,-cost,G[from].size());
	G[from].push_back(e1);
	G[to].push_back(e2);
}
void min_cost_flow(int s, int t, int f){
	vi res=zero;
	fill(h,h+V,zero);
	while(f>0){
		priority_queue< P,vector<P>,greater<P> > que;
		fill(dist,dist+V,vinf);
		dist[s]=zero;
		que.push(P(zero,s));
		while(!que.empty()){
			P p=que.top();
			que.pop();
			int v=p.second;
			if(dist[v]<p.first) continue;
			rep(i,G[v].size()){
				edge &e=G[v][i];
				if(e.cap>0 && dist[e.to]>dist[v]+e.cost+h[v]-h[e.to]){
					dist[e.to]=dist[v]+e.cost+h[v]-h[e.to];
					prevv[e.to]=v;
					preve[e.to]=i;
					que.push(P(dist[e.to],e.to));
				}
			}
		}
//		if(dist[t]==vinf) return -1;
		for(int v=0;v<V;v++) h[v]=h[v]+dist[v];
		int d=f;
		for(int v=t;v!=s;v=prevv[v]){
			d=min(d,G[prevv[v]][preve[v]].cap);
		}
		f-=d;
		res=res+d*h[t];
		for(int v=t;v!=s;v=prevv[v]){
			edge &e=G[prevv[v]][preve[v]];
			e.cap-=d;
			G[v][e.rev].cap+=d;
		}
	}
}
vi tovi(int x){
	vi ret(52,0);
	ret[x]++;
	return ret;
}
int toint(vi vv){
	rep(i,52) if(vv[i]==52) return i;
	assert(false);
}
int num(char c){
	if('A'<=c&&c<='Z') return c-'A';
	return c-'a'+26;
}
char denum(int num){
	if(num<26) return 'A'+num;
	return 'a'+(num-26);
}
int main(){
	int N;
	cin>>N;
	string st[50];
	rep(i,N) cin>>st[i];
	rep(i,N){
		rep(j,N){
			add_edge(i,j+N,1,mx-tovi(num(st[i][j])));
		}
	}
	int s=2*N,t=2*N+1;
	V=2*N+2;
	rep(i,N) add_edge(s,i,1,zero);
	rep(i,N) add_edge(N+i,t,1,zero);
	string ans;
	min_cost_flow(s,t,N);
	rep(i,N){
		for(edge e:G[i]){
			if(e.cap==0) ans.pb(denum(toint(e.cost)));
		}
	}
	sort(all(ans));
	cout<<ans<<endl;
}
### Prompt

Develop a solution in cpp to the problem described below:

Example

Input

3
aab
czc
baa


Output

aac

### Response

```cpp
#include <iostream>
#include <cstdio>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <deque>
#include <stack>
#include <algorithm>
#include <cstring>
#include <functional>
#include <cmath>
#include <utility>
#include <cassert>
using namespace std;
#define rep(i,n) for(int i=0;i<(n);++i)
#define rep1(i,n) for(int i=1;i<=(n);++i)
#define all(c) (c).begin(),(c).end()
#define fs first
#define sc second
#define pb push_back
#define show(x) cout << #x << " " << x << endl
typedef vector<int> vi;
typedef pair<vi,int> P;
struct edge {
	int to,cap;
	vi cost;
	int rev;
	edge(int to,int cap,vi cost,int rev):to(to),cap(cap),cost(cost),rev(rev){}
};
const int MAX_V=102;
int V;
vector<edge> G[MAX_V];
vi h[MAX_V];
vi dist[MAX_V];
int prevv[MAX_V],preve[MAX_V];
vi zero(52,0),mx(52,53),vinf(52,200);
vi operator +(const vi &l,const vi &r){
	vi ret=l;
	rep(i,52) ret[i]+=r[i];
	return ret;
}
vi operator -(const vi &l,const vi &r){
	vi ret=l;
	rep(i,52) ret[i]-=r[i];
	return ret;
}
vi operator*(const int &l,const vi &r){
	vi ret=r;
	rep(i,52) ret[i]+=l;
	return ret;
}
vi operator -(const vi &l){
	vi ret=l;
	rep(i,52) ret[i]=-ret[i];
	return ret;
}
void add_edge(int from, int to, int cap, vi cost){
	edge e1=edge(to,cap,cost,G[to].size()),e2(from,0,-cost,G[from].size());
	G[from].push_back(e1);
	G[to].push_back(e2);
}
void min_cost_flow(int s, int t, int f){
	vi res=zero;
	fill(h,h+V,zero);
	while(f>0){
		priority_queue< P,vector<P>,greater<P> > que;
		fill(dist,dist+V,vinf);
		dist[s]=zero;
		que.push(P(zero,s));
		while(!que.empty()){
			P p=que.top();
			que.pop();
			int v=p.second;
			if(dist[v]<p.first) continue;
			rep(i,G[v].size()){
				edge &e=G[v][i];
				if(e.cap>0 && dist[e.to]>dist[v]+e.cost+h[v]-h[e.to]){
					dist[e.to]=dist[v]+e.cost+h[v]-h[e.to];
					prevv[e.to]=v;
					preve[e.to]=i;
					que.push(P(dist[e.to],e.to));
				}
			}
		}
//		if(dist[t]==vinf) return -1;
		for(int v=0;v<V;v++) h[v]=h[v]+dist[v];
		int d=f;
		for(int v=t;v!=s;v=prevv[v]){
			d=min(d,G[prevv[v]][preve[v]].cap);
		}
		f-=d;
		res=res+d*h[t];
		for(int v=t;v!=s;v=prevv[v]){
			edge &e=G[prevv[v]][preve[v]];
			e.cap-=d;
			G[v][e.rev].cap+=d;
		}
	}
}
vi tovi(int x){
	vi ret(52,0);
	ret[x]++;
	return ret;
}
int toint(vi vv){
	rep(i,52) if(vv[i]==52) return i;
	assert(false);
}
int num(char c){
	if('A'<=c&&c<='Z') return c-'A';
	return c-'a'+26;
}
char denum(int num){
	if(num<26) return 'A'+num;
	return 'a'+(num-26);
}
int main(){
	int N;
	cin>>N;
	string st[50];
	rep(i,N) cin>>st[i];
	rep(i,N){
		rep(j,N){
			add_edge(i,j+N,1,mx-tovi(num(st[i][j])));
		}
	}
	int s=2*N,t=2*N+1;
	V=2*N+2;
	rep(i,N) add_edge(s,i,1,zero);
	rep(i,N) add_edge(N+i,t,1,zero);
	string ans;
	min_cost_flow(s,t,N);
	rep(i,N){
		for(edge e:G[i]){
			if(e.cap==0) ans.pb(denum(toint(e.cost)));
		}
	}
	sort(all(ans));
	cout<<ans<<endl;
}
```