#include <iostream>
#include <vector>
#include <queue>
using namespace std;

vector< vector<long long> > graph;
vector< vector<long long> > cost;
vector<long long> trainCost;
vector<int> removeTrain;
struct distType
{
	long long dist;
	long long index;

	distType (long long in, long long d)
	{
		dist = d;
		index = in;
	}
};

void dijkstra(long long src, long long n)
{
	queue<distType> distQueue;
	for(int i = 0;i < graph[src].size();i++)
		distQueue.push(distType(graph[src][i], cost[src][i]));
	vector<long long>dist;
	for(long long i = 0;i <= n;i++)
		dist.push_back(-1);
	dist[src] = 0;

	while(!distQueue.empty())
	{
		long long minDist = distQueue.front().dist;
		long long minPoint = distQueue.front().index;
		distQueue.pop();
		if (dist[minPoint] != -1 && dist[minPoint] <= minDist)
			continue;
		dist[minPoint] = minDist;

		if (trainCost[minPoint] >= minDist)
			removeTrain[minPoint] = 1;
		for(long long j = 0;j < graph[minPoint].size();j++)
			if (dist[graph[minPoint][j]] == -1
				|| (dist[graph[minPoint][j]] > minDist + cost[minPoint][j]))
			{
				long long newDist = minDist + cost[minPoint][j];
				distQueue.push(distType(graph[minPoint][j], newDist));
			}
	}
}

int main()
{
	long long n, m, k;
	cin >> n >> m >> k;

	graph.resize(n + 1);
	cost.resize(n + 1);
	for(long long i = 0;i <= n;i++)
	{
		vector<long long> a;
		graph.push_back(a);
		cost.push_back(a);
	}
	for(long long i = 0;i < m;i++)
	{
		long long ui, vi, xi;
		cin >> ui >> vi >> xi;
		ui--;
		vi--;
		int updated = 0;
		for(long long j = 0;j < graph[ui].size();j++)
			if (graph[ui][j] == vi)
			{
				cost[ui][j] = cost[ui][j] < xi ? cost[ui][j] : xi;
				for(long long k = 0;k < graph[vi].size();k++)
					if (graph[vi][k] == ui)
					{
						cost[vi][k] = cost[vi][k] < xi ? cost[vi][k] : xi;
						break;
					}
				updated = 1;
				break;
			}
		if (!updated)
		{
			graph[ui].push_back(vi);
			cost[ui].push_back(xi);
			graph[vi].push_back(ui);
			cost[vi].push_back(xi);
		}
	}

	long long res = 0;
	trainCost.resize(n + 1);
	for(long long i = 0;i <= n;i++)
		trainCost[i] = -1;
	trainCost[0] = 0;
	removeTrain.resize(n + 1);
	for(long long i = 0;i <= n;i++)
		removeTrain[i] = 0;
	for(long long i = 0;i < k;i++)
	{
		long long si, yi;
		cin >> si >> yi;
		si--;
		res += (trainCost[si] != -1);
		if (trainCost[si] == -1 || trainCost[si] > yi)
			trainCost[si] = yi;
	}

	dijkstra(0, n);
	for(long long i = 0;i <= n;i++)
		if (trainCost[i] && removeTrain[i])
			res++;
	cout << res << endl;
	return 0;
}


#include <iostream>
#include <vector>
#include <queue>
using namespace std;

vector< vector<long long> > graph;
vector< vector<long long> > cost;
vector<long long> trainCost;
vector<int> removeTrain;
struct distType
{
	long long dist;
	long long index;

	distType (long long in, long long d)
	{
		dist = d;
		index = in;
	}
};

void dijkstra(long long src, long long n)
{
	queue<distType> distQueue;
	for(int i = 0;i < graph[src].size();i++)
		distQueue.push(distType(graph[src][i], cost[src][i]));
	vector<long long>dist;
	for(long long i = 0;i <= n;i++)
		dist.push_back(-1);
	dist[src] = 0;

	while(!distQueue.empty())
	{
		long long minDist = distQueue.front().dist;
		long long minPoint = distQueue.front().index;
		distQueue.pop();
		if (minDist < 0)
			while(1);
		dist[minPoint] = minDist;
		if (trainCost[minPoint] >= minDist)
			removeTrain[minPoint] = 1;
		else if (trainCost[minPoint] != -1 && trainCost[minPoint] < dist[minPoint])
			dist[minPoint] = trainCost[minPoint];

		for(long long j = 0;j < graph[minPoint].size();j++)
			if (dist[graph[minPoint][j]] == -1
				|| (dist[graph[minPoint][j]] > dist[minPoint] + cost[minPoint][j]))
			{
				long long newDist = dist[minPoint] + cost[minPoint][j];
				distQueue.push(distType(graph[minPoint][j], newDist));
			}
	}
}

int main()
{
	long long n, m, k;
	cin >> n >> m >> k;

	for(long long i = 0;i <= n;i++)
	{
		vector<long long> a;
		graph.push_back(a);
		cost.push_back(a);
	}
	for(long long i = 0;i < m;i++)
	{
		long long ui, vi, xi;
		cin >> ui >> vi >> xi;
		ui--;
		vi--;
		int updated = 0;
		for(long long j = 0;j < graph[ui].size();j++)
			if (graph[ui][j] == vi)
			{
				cost[ui][j] = cost[ui][j] < xi ? cost[ui][j] : xi;
				for(long long k = 0;k < graph[vi].size();k++)
					if (graph[vi][k] == ui)
					{
						cost[vi][k] = cost[vi][k] < xi ? cost[vi][k] : xi;
						break;
					}
				updated = 1;
				break;
			}
		if (!updated)
		{
			graph[ui].push_back(vi);
			cost[ui].push_back(xi);
			graph[vi].push_back(ui);
			cost[vi].push_back(xi);
		}
	}

	long long res = 0;
	trainCost.resize(n + 1);
	for(long long i = 0;i <= n;i++)
		trainCost[i] = -1;
	trainCost[0] = 0;
	removeTrain.resize(n + 1);
	for(long long i = 0;i <= n;i++)
		removeTrain[i] = 0;
	for(long long i = 0;i < k;i++)
	{
		long long si, yi;
		cin >> si >> yi;
		si--;
		res += (trainCost[si] != -1);
		if (trainCost[si] == -1 || trainCost[si] > yi)
			trainCost[si] = yi;
	}

	dijkstra(0, n);
	for(long long i = 0;i < n;i++)
		if (removeTrain[i])
			res++;
	cout << res << endl;
	return 0;
}


#include <iostream>
#include <vector>
#include <queue>
using namespace std;

vector< vector<long long> > graph;
vector< vector<long long> > cost;
vector<long long> trainCost;
vector<int> removeTrain;
struct distType
{
	long long dist;
	long long index;

	distType (long long in, long long d)
	{
		dist = d;
		index = in;
	}
};

void dijkstra(long long src, long long n)
{
	queue<distType> distQueue;
	for(int i = 0;i < graph[src].size();i++)
		distQueue.push(distType(graph[src][i], cost[src][i]));
	vector<long long>dist;
	for(long long i = 0;i <= n;i++)
		dist.push_back(-1);
	dist[src] = 0;

	while(!distQueue.empty())
	{
		long long minDist = distQueue.front().dist;
		long long minPoint = distQueue.front().index;
		distQueue.pop();
		if (dist[minPoint] != -1 && trainCost[minPoint] != -1
			&& dist[minPoint] > trainCost[minPoint])
			while(1);
		if (dist[minPoint] != -1 && dist[minPoint] <= minDist)
			continue;
		dist[minPoint] = minDist;
		if (trainCost[minPoint] >= minDist)
			removeTrain[minPoint] = 1;
		else if (trainCost[minPoint] != -1 && trainCost[minPoint] < dist[minPoint])
			dist[minPoint] = trainCost[minPoint];

		for(long long j = 0;j < graph[minPoint].size();j++)
		{
			long long newDist = dist[minPoint] + cost[minPoint][j];
			distQueue.push(distType(graph[minPoint][j], newDist));
		}
	}
}

int main()
{
	long long n, m, k;
	cin >> n >> m >> k;

	for(long long i = 0;i <= n;i++)
	{
		vector<long long> a;
		graph.push_back(a);
		cost.push_back(a);
	}
	for(long long i = 0;i < m;i++)
	{
		long long ui, vi, xi;
		cin >> ui >> vi >> xi;
		ui--;
		vi--;
		int updated = 0;
		for(long long j = 0;j < graph[ui].size();j++)
			if (graph[ui][j] == vi)
			{
				cost[ui][j] = cost[ui][j] < xi ? cost[ui][j] : xi;
				for(long long k = 0;k < graph[vi].size();k++)
					if (graph[vi][k] == ui)
					{
						cost[vi][k] = cost[vi][k] < xi ? cost[vi][k] : xi;
						break;
					}
				updated = 1;
				break;
			}
		if (!updated)
		{
			graph[ui].push_back(vi);
			cost[ui].push_back(xi);
			graph[vi].push_back(ui);
			cost[vi].push_back(xi);
		}
	}

	long long res = 0;
	trainCost.resize(n + 1);
	for(long long i = 0;i <= n;i++)
		trainCost[i] = -1;
	trainCost[0] = 0;
	removeTrain.resize(n + 1);
	for(long long i = 0;i <= n;i++)
		removeTrain[i] = 0;
	for(long long i = 0;i < k;i++)
	{
		long long si, yi;
		cin >> si >> yi;
		si--;
		res += (trainCost[si] != -1);
		if (trainCost[si] == -1 || trainCost[si] > yi)
			trainCost[si] = yi;
	}

	dijkstra(0, n);
	for(long long i = 0;i < n;i++)
		if (removeTrain[i])
			res++;
	cout << res << endl;
	return 0;
}


#include <iostream>
#include <vector>
#include <queue>
using namespace std;

vector< vector<int> > graph;
vector< vector<int> > cost;
vector<int> trainCost;
vector<int> removeTrain;
struct distType
{
	long long dist;
	int index;

	distType (int in, long long d)
	{
		dist = d;
		index = in;
	}

	friend bool operator < (const distType a, const distType b)
	{
		if (a.dist >= b.dist)
			return 1;
		else
			return 0;
	}
};

void dijkstra(int src, int n)
{
	priority_queue<distType> distQueue;
	for(int i = 0;i < graph[src].size();i++)
		distQueue.push(distType(graph[src][i], cost[src][i]));
	vector<long long>dist;
	for(int i = 0;i <= n;i++)
		dist.push_back(-1);
	dist[src] = 0;

	while(!distQueue.empty())
	{
		long long minDist = distQueue.top().dist;
		int minPoint = distQueue.top().index;
		distQueue.pop();

		if (dist[minPoint] == -1)
		{
			if (trainCost[minPoint] != -1 && minDist > trainCost[minPoint])
				minDist = trainCost[minPoint];
			dist[minPoint] = minDist;
		}
		else
		{
			if (trainCost[minPoint] >= dist[minPoint])
				removeTrain[minPoint] = 1;
			continue;
		}
		for(int j = 0;j < graph[minPoint].size();j++)
		{
			long long newDist = dist[minPoint] + cost[minPoint][j];
			distQueue.push(distType(graph[minPoint][j], newDist));
		}
	}
}

int main()
{
	int n, m, k;
	cin >> n >> m >> k;

	for(int i = 0;i <= n;i++)
	{
		vector<int> a;
		graph.push_back(a);
		cost.push_back(a);
	}
	for(int i = 0;i < m;i++)
	{
		int ui, vi, xi;
		cin >> ui >> vi >> xi;
		ui--;
		vi--;
		int updated = 0;
		for(int j = 0;j < graph[ui].size();j++)
			if (graph[ui][j] == vi)
			{
				if (cost[ui][j] > xi)	cost[ui][j] = xi;
				for(int k = 0;k < graph[vi].size();k++)
					if (graph[vi][k] == ui)
					{
						if (cost[vi][k] > xi)	cost[vi][k] = xi;
						break;
					}
				updated = 1;
				break;
			}
		if (!updated)
		{
			graph[ui].push_back(vi);
			cost[ui].push_back(xi);
			graph[vi].push_back(ui);
			cost[vi].push_back(xi);
		}
	}

	long long res = 0;
	trainCost.resize(n + 1);
	for(int i = 0;i <= n;i++)
		trainCost[i] = -1;
	trainCost[0] = 0;
	removeTrain.resize(n + 1);
	for(int i = 0;i <= n;i++)
		removeTrain[i] = 0;
	for(int i = 0;i < k;i++)
	{
		int si, yi;
		cin >> si >> yi;
		si--;
		res += (trainCost[si] != -1);
		if (trainCost[si] == -1 || trainCost[si] > yi)
			trainCost[si] = yi;
	}

	dijkstra(0, n);
	for(int i = 0;i < n;i++)
		if (removeTrain[i])
			res++;
	cout << res << endl;

	return 0;
}


#include <iostream>
#include <vector>
#include <queue>
using namespace std;

vector< vector<long long> > graph;
vector< vector<long long> > cost;
vector<long long> trainCost;
vector<int> removeTrain;
struct distType
{
	long long dist;
	int index;

	distType (int in, long long d)
	{
		dist = d;
		index = in;
	}
};

void dijkstra(int src, int n)
{
	queue<distType> distQueue;
	for(int i = 0;i < graph[src].size();i++)
		distQueue.push(distType(graph[src][i], cost[src][i]));
	vector<int> found;
	for(int i = 0;i <= n;i++)
		found.push_back(0);
	found[src] = 1;
	vector<long long>dist;
	for(int i = 0;i <= n;i++)
		dist.push_back(-1);
	dist[src] = 0;

	int ff = 0;
	while(!distQueue.empty())
	{
		ff++;
		if (ff > 300000)
		{
			cout << ff << endl;
			break;
		}
		long long minDist = -1;
		long long minPoint = -1;
		minDist = distQueue.front().dist;
		minPoint = distQueue.front().index;
		distQueue.pop();
		if (dist[minPoint] != -1 && dist[minPoint] <= minDist)
			continue;

		dist[minPoint] = minDist;
		if (trainCost[minPoint] < minDist)
		{
			int updated = 0;
			for(int j = 0;j < graph[src].size();j++)
				if (graph[src][j] == minPoint)
				{
					cost[src][j] = trainCost[minPoint];
					updated = 1;

					for(int k = 0;k < graph[minPoint].size();k++)
						if (graph[minPoint][k] == src)
						{
							cost[minPoint][k] = trainCost[minPoint];
							break;
						}
					break;
				}
			if (!updated)
			{
				graph[src].push_back(minPoint);
				cost[src].push_back(trainCost[minPoint]);
				graph[minPoint].push_back(src);
				cost[minPoint].push_back(trainCost[minPoint]);
			}
		}
		else
			removeTrain[minPoint] = 1;

		for(int j = 0;j < graph[minPoint].size();j++)
			if (dist[graph[minPoint][j]] == -1
				|| (dist[graph[minPoint][j]] > minDist + cost[minPoint][j]))
			{
				long long newDist = minDist + cost[minPoint][j];
				distQueue.push(distType(graph[minPoint][j], newDist));
			}
		found[minPoint] = 1;
	}
}

int main()
{
	int n, m, k;
	cin >> n >> m >> k;

	graph.resize(n + 1);
	cost.resize(n + 1);
	for(int i = 0;i <= n;i++)
	{
		vector<long long> a;
		graph.push_back(a);
		cost.push_back(a);
	}
	for(int i = 0;i < m;i++)
	{
		int ui, vi, xi;
		cin >> ui >> vi >> xi;
		ui--;
		vi--;
		int updated = 0;
		for(int j = 0;j < graph[ui].size();j++)
			if (graph[ui][j] == vi)
			{
				cost[ui][j] = cost[ui][j] < xi ? cost[ui][j] : xi;
				for(int k = 0;k < graph[vi].size();k++)
					if (graph[vi][k] == ui)
					{
						cost[vi][k] = cost[vi][k] < xi ? cost[vi][k] : xi;
						break;
					}
				updated = 1;
				break;
			}
		if (!updated)
		{
			graph[ui].push_back(vi);
			cost[ui].push_back(xi);
			graph[vi].push_back(ui);
			cost[vi].push_back(xi);
		}
	}

	long long res = 0;
	trainCost.resize(n + 1);
	for(int i = 0;i <= n;i++)
		trainCost[i] = -1;
	trainCost[0] = 0;
	removeTrain.resize(n + 1);
	for(int i = 0;i <= n;i++)
		removeTrain[i] = 0;
	for(int i = 0;i < k;i++)
	{
		int si, yi;
		cin >> si >> yi;
		si--;
		res += (trainCost[si] != -1);
		if (trainCost[si] == -1 || trainCost[si] > yi)
			trainCost[si] = yi;
	}

	dijkstra(0, n);
	for(int i = 0;i <= n;i++)
		if (trainCost[i] && removeTrain[i])
			res++;
	cout << res << endl;
	return 0;
}


#include <iostream>
#include <vector>
#include <queue>
using namespace std;

vector< vector<long long> > graph;
vector< vector<long long> > cost;
vector<long long> trainCost;
vector<int> removeTrain;
struct distType
{
	long long dist;
	long long index;

	distType (long long in, long long d)
	{
		dist = d;
		index = in;
	}
};

void dijkstra(long long src, long long n)
{
	queue<distType> distQueue;
	for(int i = 0;i < graph[src].size();i++)
		distQueue.push(distType(graph[src][i], cost[src][i]));
	vector<long long>dist;
	for(long long i = 0;i <= n;i++)
		dist.push_back(-1);
	dist[src] = 0;

	while(!distQueue.empty())
	{
		long long minDist = distQueue.front().dist;
		long long minPoint = distQueue.front().index;
		distQueue.pop();
		if (dist[minPoint] != -1 && dist[minPoint] <= minDist)
			continue;
		if (minDist < 0)
			while(1);
		dist[minPoint] = minDist;
		if (trainCost[minPoint] >= minDist)
			removeTrain[minPoint] = 1;
		else if (trainCost[minPoint] != -1 && trainCost[minPoint] < dist[minPoint])
			dist[minPoint] = trainCost[minPoint];

		for(long long j = 0;j < graph[minPoint].size();j++)
			if (dist[graph[minPoint][j]] == -1
				|| (dist[graph[minPoint][j]] > dist[minPoint] + cost[minPoint][j]))
			{
				long long newDist = dist[minPoint] + cost[minPoint][j];
				distQueue.push(distType(graph[minPoint][j], newDist));
			}
	}
}

int main()
{
	long long n, m, k;
	cin >> n >> m >> k;

	for(long long i = 0;i <= n;i++)
	{
		vector<long long> a;
		graph.push_back(a);
		cost.push_back(a);
	}
	for(long long i = 0;i < m;i++)
	{
		long long ui, vi, xi;
		cin >> ui >> vi >> xi;
		ui--;
		vi--;
		int updated = 0;
		for(long long j = 0;j < graph[ui].size();j++)
			if (graph[ui][j] == vi)
			{
				cost[ui][j] = cost[ui][j] < xi ? cost[ui][j] : xi;
				for(long long k = 0;k < graph[vi].size();k++)
					if (graph[vi][k] == ui)
					{
						cost[vi][k] = cost[vi][k] < xi ? cost[vi][k] : xi;
						break;
					}
				updated = 1;
				break;
			}
		if (!updated)
		{
			graph[ui].push_back(vi);
			cost[ui].push_back(xi);
			graph[vi].push_back(ui);
			cost[vi].push_back(xi);
		}
	}

	long long res = 0;
	trainCost.resize(n + 1);
	for(long long i = 0;i <= n;i++)
		trainCost[i] = -1;
	trainCost[0] = 0;
	removeTrain.resize(n + 1);
	for(long long i = 0;i <= n;i++)
		removeTrain[i] = 0;
	for(long long i = 0;i < k;i++)
	{
		long long si, yi;
		cin >> si >> yi;
		si--;
		res += (trainCost[si] != -1);
		if (trainCost[si] == -1 || trainCost[si] > yi)
			trainCost[si] = yi;
	}

	dijkstra(0, n);
	for(long long i = 0;i < n;i++)
		if (removeTrain[i])
			res++;
	cout << res << endl;
	return 0;
}


#include <iostream>
#include <vector>
#include <queue>
using namespace std;

vector< vector<long long> > graph;
vector< vector<long long> > cost;
vector<long long> trainCost;
vector<int> removeTrain;
struct distType
{
	long long dist;
	long long index;

	distType (long long in, long long d)
	{
		dist = d;
		index = in;
	}
};

void dijkstra(long long src, long long n)
{
	queue<distType> distQueue;
	for(int i = 0;i < graph[src].size();i++)
		distQueue.push(distType(graph[src][i], cost[src][i]));
	vector<long long>dist;
	for(long long i = 0;i <= n;i++)
		dist.push_back(-1);
	dist[src] = 0;

	while(!distQueue.empty())
	{
		long long minDist = distQueue.front().dist;
		long long minPoint = distQueue.front().index;
		distQueue.pop();
		if (dist[minPoint] != -1 && dist[minPoint] <= minDist)
			continue;
		if (minDist < 0)
			while(1);
		dist[minPoint] = minDist;
		if (trainCost[minPoint] >= minDist)
			removeTrain[minPoint] = 1;
		else if (trainCost[minPoint] != -1 && trainCost[minPoint] < dist[minPoint])
			dist[minPoint] = trainCost[minPoint];

		for(long long j = 0;j < graph[minPoint].size();j++)
		{
			long long newDist = dist[minPoint] + cost[minPoint][j];
			distQueue.push(distType(graph[minPoint][j], newDist));
		}
	}
}

int main()
{
	long long n, m, k;
	cin >> n >> m >> k;

	for(long long i = 0;i <= n;i++)
	{
		vector<long long> a;
		graph.push_back(a);
		cost.push_back(a);
	}
	for(long long i = 0;i < m;i++)
	{
		long long ui, vi, xi;
		cin >> ui >> vi >> xi;
		ui--;
		vi--;
		int updated = 0;
		for(long long j = 0;j < graph[ui].size();j++)
			if (graph[ui][j] == vi)
			{
				cost[ui][j] = cost[ui][j] < xi ? cost[ui][j] : xi;
				for(long long k = 0;k < graph[vi].size();k++)
					if (graph[vi][k] == ui)
					{
						cost[vi][k] = cost[vi][k] < xi ? cost[vi][k] : xi;
						break;
					}
				updated = 1;
				break;
			}
		if (!updated)
		{
			graph[ui].push_back(vi);
			cost[ui].push_back(xi);
			graph[vi].push_back(ui);
			cost[vi].push_back(xi);
		}
	}

	long long res = 0;
	trainCost.resize(n + 1);
	for(long long i = 0;i <= n;i++)
		trainCost[i] = -1;
	trainCost[0] = 0;
	removeTrain.resize(n + 1);
	for(long long i = 0;i <= n;i++)
		removeTrain[i] = 0;
	for(long long i = 0;i < k;i++)
	{
		long long si, yi;
		cin >> si >> yi;
		si--;
		res += (trainCost[si] != -1);
		if (trainCost[si] == -1 || trainCost[si] > yi)
			trainCost[si] = yi;
	}

	dijkstra(0, n);
	for(long long i = 0;i < n;i++)
		if (removeTrain[i])
			res++;
	cout << res << endl;
	return 0;
}


#include <iostream>
#include <vector>
#include <queue>
using namespace std;

vector< vector<int> > graph;
vector< vector<int> > cost;
vector<int> trainCost;
vector<int> removeTrain;
struct distType
{
    long long dist;
    int index;

    distType (int in, long long d)
    {
        dist = d;
        index = in;
    }

    friend bool operator < (const distType a, const distType b)
    {
        if (a.dist > b.dist)
            return 1;
        else
            return 0;
    }
};

void dijkstra(int src, int n)
{
    vector<long long>dist;
    priority_queue<distType> distQueue;

    for(int i = 0;i <= n;i++)
    {
        if (trainCost[i] > 0)
            dist.push_back(trainCost[i]);
        else
            dist.push_back(1e18);
        if (trainCost[i] > 0)
            distQueue.push(distType(i, trainCost[i]));
    }
    dist[0] = 0;
    distQueue.push(distType(0, 0));
    /*
    for(int i = 0;i < graph[src].size();i++)
    {
        if (dist[graph[src][i]] == -1 || dist[graph[src][i]] > cost[src][i])
            dist[graph[src][i]] = cost[src][i];
    }
    */

    vector<int> visit;
    visit.resize(n + 1);
    for(int i = 0;i <= n;i++)
        visit[i] = 0;

    while(!distQueue.empty())
    {
        long long minDist = distQueue.top().dist;
        int minPoint = distQueue.top().index;
        distQueue.pop();

     //   cout << minPoint << " " << minDist << endl;
        if (visit[minPoint] == 1)
            removeTrain[minPoint] = 1;

        if (visit[minPoint])
            continue;
        visit[minPoint] = 1;

        for(int j = 0;j < graph[minPoint].size();j++)
        {
            long long newDist = minDist + cost[minPoint][j];
            if (dist[graph[minPoint][j]] >= newDist)
            {
                distQueue.push(distType(graph[minPoint][j], newDist));
                dist[graph[minPoint][j]] = newDist;
            }
        }
    }
}

int main()
{
    int n, m, k;
    cin >> n >> m >> k;

    for(int i = 0;i <= n;i++)
    {
        vector<int> a;
        graph.push_back(a);
        cost.push_back(a);
    }
    for(int i = 0;i < m;i++)
    {
        int ui, vi, xi;
        cin >> ui >> vi >> xi;
        ui--;
        vi--;
        int updated = 0;
      /*  for(int j = 0;j < graph[ui].size();j++)
            if (graph[ui][j] == vi)
            {
                if (cost[ui][j] > xi)   cost[ui][j] = xi;
                for(int k = 0;k < graph[vi].size();k++)
                    if (graph[vi][k] == ui)
                    {
                        if (cost[vi][k] > xi)   cost[vi][k] = xi;
                        break;
                    }
                updated = 1;
                break;
            }
            */
        if (!updated)
        {
            graph[ui].push_back(vi);
            cost[ui].push_back(xi);
            graph[vi].push_back(ui);
            cost[vi].push_back(xi);
        }
    }

    long long res = 0;
    trainCost.resize(n + 1);
    for(int i = 0;i <= n;i++)
        trainCost[i] = -1;
    trainCost[0] = 0;
    removeTrain.resize(n + 1);
    for(int i = 0;i <= n;i++)
        removeTrain[i] = 0;
    for(int i = 0;i < k;i++)
    {
        int si, yi;
        cin >> si >> yi;
        si--;
        res += (trainCost[si] != -1);
        if (trainCost[si] == -1 || trainCost[si] > yi)
            trainCost[si] = yi;
    }

    dijkstra(0, n);
    for(int i = 0;i < n;i++)
        if (removeTrain[i])
            res++;
    cout << res << endl;

    return 0;
}


#include<bits/stdc++.h>
#define rep(i, n) for(int i = 1; i <= n; ++i)
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<pair<int, int>, int > p3;
const int maxn = 2039;
int n, k;
char s[maxn][maxn];
pii fa[maxn][maxn];
bitset<maxn> inq[maxn];
inline bool valid(int x, int y) {
    return x >= 1 && x <= n && y >= 1 && y <= n;
}
int main(){
    #ifdef FREOPEN
        freopen("in.txt", "r", stdin);
        // freopen("out.txt", "w", stdout);
    #endif
    int layer, bst = 'z' + 1;
    vector<pii> tobe;
    string ans = "";

    scanf("%d%d", &n, &k);
    int goal = 1;
    queue<pii> q;
    rep(i, n) scanf("%s", s[i] + 1);
    queue<p3> qq;
    if(k == 0) {
        ans += s[1][1];
    }
    if(s[1][1] == 'a') qq.push({{1, 1}, 0});
    else {
        qq.push({{1, 1}, 1});
    }
    while(!qq.empty()) {
        p3 cur = qq.front(); qq.pop();
        int x = cur.first.first, y = cur.first.second, t = cur.second;
        if(t > k) break;
        if(t == k) {
            if(x + y > goal) {
                while(!q.empty()) {
                    auto cur = q.front();
                    inq[cur.first][cur.second] = false;
                    q.pop();
                }
            }
            if(!inq[x][y])
                q.push({x, y}),
                inq[x][y] = true;
            goal = x + y;
        }
        if(t <= k) {
            if(s[x + 1][y] == 'a' && valid(x + 1, y)) {
                qq.push(make_pair(make_pair(x + 1, y), t));
            } else if(t + 1 <= k) qq.push(make_pair(make_pair(x + 1, y), t + 1));
            if (s[x][y + 1] == 'a' && valid(x, y + 1)) {
                qq.push({make_pair(x, y + 1), t});
            } else if(t + 1 <= k)qq.push({make_pair(x, y + 1), t + 1});
        }
    }

    layer = goal;
    if(k > 0) rep(i, goal - 1) ans += "a";
    while(layer <= 2 * n) {
        if(q.empty()) {
            layer++;
            for(auto v : tobe) {
                q.push(v);
            }
            bst = 'z' + 1;
            if(layer >= 2 * n) break;
            continue;
        }
        auto cur = q.front(); q.pop();
        int x = cur.first, y = cur.second;
        if(x + y == layer) {
            if(valid(x + 1, y) && s[x + 1][y] < bst) {
                tobe.clear();
                bst = s[x + 1][y];
                fa[x + 1][y] = {x, y};
                tobe.push_back({x + 1, y});
            } else if (valid(x + 1, y) && s[x + 1][y] == bst) {
                fa[x + 1][y] = {x, y};
                tobe.push_back({x + 1, y});
            }

            if(valid(x, y + 1) && s[x][y + 1] < bst) {
                tobe.clear();
                bst = s[x][y + 1];
                fa[x][y + 1] = {x, y};
                tobe.push_back({x, y + 1});
            } else if (valid(x, y + 1) && s[x][y + 1] == bst) {
                fa[x][y + 1] = {x, y};
                tobe.push_back({x, y + 1});
            }
        }
        else {
            assert(false);
        }
    }
    pii cur = {n, n};
    stack<char> st;
    rep(i, 2 * n - goal) st.push(s[cur.first][cur.second]), cur = fa[cur.first][cur.second];
    while(!st.empty()) ans += st.top(), st.pop();
    cout << ans << endl;
    return 0;
}


#include <iostream>
#include <vector>
#include <utility>
using namespace std;
typedef long long ll;
const int INF = 1e9;

const int N = 2000;
string arr[N];
int dp[N][N];
pair<int, int> pre[N][N];
int n;

void offer(pair<int, int> t, pair <int, int> p) {
	int x = t.first;
	int y = t.second;
	if (x > n || y > n) return;
	int off = dp[p.first][p.second] + (arr[x][y] != 'a');
	if (off < dp[x][y]) {
		dp[x][y] = off;
		pre[x][y] = p;
	}
}

int main() {
	ios_base::sync_with_stdio(false);
	cin.tie(0);

	int k;
	cin >> n >> k;
	for (int y = 0; y < n; ++y) cin >> arr[y];

	// 1. Find longest path with at most k non-a's
	for (int x = 0; x < n; ++x) {
		for (int y = 0; y < n; ++y) {
			dp[x][y] = INF;
		}
	}

	int max_sum = 0;
	dp[0][0] = (arr[0][0] != 'a');
	pre[0][0] = {-1, -1};
	for (int x = 0; x < n; ++x) {
		for (int y = 0; y < n; ++y) {
			if (dp[x][y] <= k) max_sum = max(max_sum, x + y);
			offer({x+1, y}, {x, y});
			offer({x, y+1}, {x, y});
		}
	}

	// 2. Find rest of the path
	vector<pair<int, int>> offs;
	for (int x = 0; x < n; ++x) {
		for (int y = 0; y < n; ++y) {
			if (dp[x][y] <= k && x+y == max_sum) offs.push_back({x, y});
		}
	}
	for (; max_sum < 2 * (n-1); ++max_sum) {
		char best = 'z';
		for (auto pr : offs) {
			int x = pr.first;
			int y = pr.second;
			if (x+1 < n) best = min(best, arr[x+1][y]);
			if (y+1 < n) best = min(best, arr[x][y+1]);
		}
		vector<pair<int, int>> next_offs;
		for (auto pr : offs) {
			int x = pr.first;
			int y = pr.second;
			if (x+1 < n) {
				if (arr[x+1][y] == best && dp[x+1][y] != -1) {
					dp[x+1][y] = -1;
					pre[x+1][y] = pr;
					next_offs.push_back({x+1, y});
				}
			}
			if (y+1 < n) {
				if (arr[x][y+1] == best && dp[x][y+1] != -1) {
					dp[x][y+1] = -1;
					pre[x][y+1] = pr;
					next_offs.push_back({x, y+1});
				}
			}
		}
		offs = next_offs;
	}

	// 3. Produce answer
	string res(2*n - 1, 'a');
	pair<int, int> curr = {n-1, n-1};
	while(max_sum >= 0) {
		res[max_sum] = arr[curr.first][curr.second];
		curr = pre[curr.first][curr.second];
		--max_sum;
	}

	for (int i = 0; i < res.size(); ++i) {
		if (res[i] != 'a' && k > 0) {
			res[i] = 'a';
			--k;
		}
	}

	cout << res << '\n';
}


#include <iostream>
#include <vector>
#include <utility>
using namespace std;
typedef long long ll;
const int INF = 1e9;

const int N = 2000;
char arr[N][N];
int dp[N][N];
pair<int, int> pre[N][N];
int n;

void offer(pair<int, int> t, pair <int, int> p) {
	int x = t.first;
	int y = t.second;
	if (x >= n || y >= n) return;
	int off = dp[p.first][p.second] + (arr[x][y] != 'a');
	if (off < dp[x][y]) {
		dp[x][y] = off;
		pre[x][y] = p;
	}
}

void helper(pair<int, int> t, pair<int, int> p, vector<pair<int, int>>& next_offs, char best) {
	int x = t.first;
	int y = t.second;
	if (x >= n || y >= n) return;
	if (dp[x][y] == -1) return;
	if (arr[x][y] != best) return;
	dp[x][y] = -1;
	pre[x][y] = p;
	next_offs.push_back(t);
}

int main() {
	ios_base::sync_with_stdio(false);
	cin.tie(0);

	int k;
	cin >> n >> k;
	for (int y = 0; y < n; ++y) {
		string row;
		cin >> row;
		for (int x = 0; x < n; ++x) arr[x][y] = row[x];
	}

	// 1. Find longest path with at most k non-a's
	for (int x = 0; x < n; ++x) {
		for (int y = 0; y < n; ++y) {
			dp[x][y] = INF;
		}
	}

	int max_sum = 0;
	dp[0][0] = (arr[0][0] != 'a');
	pre[0][0] = {-1, -1};
	for (int x = 0; x < n; ++x) {
		for (int y = 0; y < n; ++y) {
			if (dp[x][y] <= k) max_sum = max(max_sum, x + y);
			offer({x+1, y}, {x, y});
			offer({x, y+1}, {x, y});
		}
	}

	// 2. Find rest of the path
	vector<pair<int, int>> offs;
	for (int x = 0; x < n; ++x) {
		for (int y = 0; y < n; ++y) {
			if (dp[x][y] <= k && x+y == max_sum) offs.push_back({x, y});
		}
	}
	if (offs.empty()) offs.push_back({0, 0});

	for (; max_sum < 2 * (n-1); ++max_sum) {
		char best = 'z';
		for (auto pr : offs) {
			int x = pr.first;
			int y = pr.second;
			if (x+1 < n) best = min(best, arr[x+1][y]);
			if (y+1 < n) best = min(best, arr[x][y+1]);
		}
		vector<pair<int, int>> next_offs;
		for (auto pr : offs) {
			int x = pr.first;
			int y = pr.second;
			helper({x+1, y}, {x, y}, next_offs, best);
			helper({x, y+1}, {x, y}, next_offs, best);
		}
		offs = next_offs;
	}

	// 3. Produce answer
	string res(2*n - 1, 'z');
	pair<int, int> curr = {n-1, n-1};
	while(max_sum >= 0) {
		res[max_sum] = arr[curr.first][curr.second];
		curr = pre[curr.first][curr.second];
		--max_sum;
	}

	for (int i = 0; i < (int)res.size(); ++i) {
		if (res[i] != 'a' && k > 0) {
			res[i] = 'a';
			--k;
		}
	}

	cout << res << '\n';
}


#include <iostream>
#include <vector>
#include <utility>
using namespace std;
typedef long long ll;
const int INF = 1e9;

const int N = 2000;
string arr[N];
int dp[N][N];
pair<int, int> pre[N][N];

int main() {
	ios_base::sync_with_stdio(false);
	cin.tie(0);

	ll n, k;
	cin >> n >> k;
	for (int y = 0; y < n; ++y) cin >> arr[y];

	// 1. Find longest path with at most k non-a's
	for (int x = 0; x < n; ++x) {
		for (int y = 0; y < n; ++y) {
			dp[x][y] = INF;
		}
	}

	int max_sum = 0;
	dp[0][0] = (arr[0][0] != 'a');
	pre[0][0] = {-1, -1};
	for (int x = 0; x < n; ++x) {
		for (int y = 0; y < n; ++y) {
			if (dp[x][y] <= k) max_sum = max(max_sum, x + y);

			if (x+1 < n) {
				int off = dp[x][y] + (arr[x+1][y] != 'a');
				if (off < dp[x+1][y]) {
					dp[x+1][y] = off;
					pre[x+1][y] = {x, y};
				}
			}
			if (y+1 < n) {
				int off = dp[x][y] + (arr[x][y+1] != 'a');
				if (off < dp[x][y+1]) {
					dp[x][y+1] = off;
					pre[x][y+1] = {x, y};
				}
			}
		}
	}

	vector<pair<int, int>> offs;
	for (int x = 0; x < n; ++x) {
		for (int y = 0; y < n; ++y) {
			if (dp[x][y] <= k && x+y == max_sum) offs.push_back({x, y});
		}
	}
	for (; max_sum < 2 * (n-1); ++max_sum) {
		char best = 'z';
		for (auto pr : offs) {
			int x = pr.first;
			int y = pr.second;
			if (x+1 < n) best = min(best, arr[x+1][y]);
			if (y+1 < n) best = min(best, arr[x][y+1]);
		}
		vector<pair<int, int>> next_offs;
		for (auto pr : offs) {
			int x = pr.first;
			int y = pr.second;
			if (x+1 < n) {
				if (arr[x+1][y] == best && dp[x+1][y] != -1) {
					dp[x+1][y] = -1;
					pre[x+1][y] = pr;
					next_offs.push_back({x+1, y});
				}
			}
			if (y+1 < n) {
				if (arr[x][y+1] == best && dp[x][y+1] != -1) {
					dp[x][y+1] = -1;
					pre[x][y+1] = pr;
					next_offs.push_back({x, y+1});
				}
			}
			offs = next_offs;
		}
	}

	string res(2*n - 1, 'a');
	pair<int, int> curr = {n-1, n-1};
	while(max_sum >= 0) {
		res[max_sum] = arr[curr.first][curr.second];
		curr = pre[curr.first][curr.second];
		--max_sum;
	}

	for (int i = 0; i < res.size(); ++i) {
		if (res[i] != 'a' && k > 0) {
			res[i] = 'a';
			--k;
		}
	}

	cout << res << '\n';
}


#include <iostream>
#include <vector>
#include <utility>
using namespace std;
typedef long long ll;
const int INF = 1e9;

const int N = 2000;
string arr[N];
int dp[N][N];
pair<int, int> pre[N][N];
int n;

void offer(pair<int, int> t, pair <int, int> p) {
	int x = t.first;
	int y = t.second;
	if (x >= n || y >= n) return;
	int off = dp[p.first][p.second] + (arr[x][y] != 'a');
	if (off < dp[x][y]) {
		dp[x][y] = off;
		pre[x][y] = p;
	}
}

void helper(pair<int, int> t, pair<int, int> p, vector<pair<int, int>>& next_offs, char best) {
	int x = t.first;
	int y = t.second;
	if (x >= n || y >= n) return;
	if (dp[x][y] == -1) return;
	if (arr[x][y] != best) return;
	dp[x][y] = -1;
	pre[x][y] = p;
	next_offs.push_back(t);
}

int main() {
	ios_base::sync_with_stdio(false);
	cin.tie(0);

	int k;
	cin >> n >> k;
	for (int y = 0; y < n; ++y) cin >> arr[y];

	// 1. Find longest path with at most k non-a's
	for (int x = 0; x < n; ++x) {
		for (int y = 0; y < n; ++y) {
			dp[x][y] = INF;
		}
	}

	int max_sum = 0;
	dp[0][0] = (arr[0][0] != 'a');
	pre[0][0] = {-1, -1};
	for (int x = 0; x < n; ++x) {
		for (int y = 0; y < n; ++y) {
			if (dp[x][y] <= k) max_sum = max(max_sum, x + y);
			offer({x+1, y}, {x, y});
			offer({x, y+1}, {x, y});
		}
	}

	// 2. Find rest of the path
	vector<pair<int, int>> offs;
	for (int x = 0; x < n; ++x) {
		for (int y = 0; y < n; ++y) {
			if (dp[x][y] <= k && x+y == max_sum) offs.push_back({x, y});
		}
	}
	for (; max_sum < 2 * (n-1); ++max_sum) {
		char best = 'z';
		for (auto pr : offs) {
			int x = pr.first;
			int y = pr.second;
			if (x+1 < n) best = min(best, arr[x+1][y]);
			if (y+1 < n) best = min(best, arr[x][y+1]);
		}
		vector<pair<int, int>> next_offs;
		for (auto pr : offs) {
			int x = pr.first;
			int y = pr.second;
			helper({x+1, y}, {x, y}, next_offs, best);
			helper({x, y+1}, {x, y}, next_offs, best);
		}
		offs = next_offs;
	}

	// 3. Produce answer
	string res(2*n - 1, 'a');
	pair<int, int> curr = {n-1, n-1};
	while(max_sum >= 0) {
		res[max_sum] = arr[curr.first][curr.second];
		curr = pre[curr.first][curr.second];
		--max_sum;
	}

	for (int i = 0; i < res.size(); ++i) {
		if (res[i] != 'a' && k > 0) {
			res[i] = 'a';
			--k;
		}
	}

	cout << res << '\n';
}


#pragma GCC optimize("Ofast,no-stack-protector")
#include <bits/stdc++.h>
#include <ext/pb_ds/detail/standard_policies.hpp>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>

#define pb push_back
#define F first
#define S second
#define ld long double
#define ll int64_t
#define endl '\n'
#define eb emplace_back
#define pb push_back
#define TIME 1.0*clock()/CLOCKS_PER_SEC
#define pii pair < int32_t , int32_t >
#define Endl '\n'
#define pll pair <ll,ll>
using namespace std;
using namespace __gnu_pbds;
typedef tree <ll,null_type,less <ll>,rb_tree_tag,tree_order_statistics_node_update> ordered_set;
mt19937_64 randomizer(chrono::duration_cast<chrono::nanoseconds>(chrono::high_resolution_clock::now().time_since_epoch()).count());
const int mod = 1e9+7;
const int number_for_MO = 1e4+111;
const int size_for_segment_trees = 1e5;
int32_t FFTM = 998244353;
const int32_t N = 50000;
int32_t SX[4] = {0 , 1 , -1 , 0};
int32_t SY[4] = {1 , 0 , 0 , -1};
int32_t main() {
#ifdef CHUCHUNDRA
freopen("input.txt", "r", stdin);
freopen("output.txt", "w", stdout);
#else
//freopen("input.txt", "r", stdin);
//freopen("output.txt", "w", stdout);
#endif
ll n,m;
cin>>n>>m;
vector <vector <char> > c(n,vector <char> (n));
vector <vector <ll> > dp(n,vector <ll> (n,1e18));
vector <vector <ll> > dp2(n,vector <ll> (n,1e18));
for (int i = 0;i < n;i++)
{
    for (int j = 0;j < n;j++)
    {
        cin>>c[i][j];
    }
}
dp[0][0] = 0;
if (c[0][0]!='a') ++dp[0][0];
dp2[0][0] = 1;
for (int i = 0;i < n;i++)
{
    for (int j = 0;j < n;j++)
    {
        if (i) dp[i][j] = min(dp[i][j],dp[i-1][j]+(c[i][j]!='a'));
        if (j) dp[i][j] = min(dp[i][j],dp[i][j-1]+(c[i][j]!='a'));
        if (i) dp2[i][j] = min(dp2[i][j],dp2[i-1][j]+1);
        if (j) dp2[i][j] = min(dp2[i][j],dp2[i][j-1]+1);
    }
}
ll mux = -1;
for (ll i = 0;i < n;i++)
{
    for (ll j = 0;j < n;j++)
    {
        if (dp[i][j]<=m) {mux = max(mux,dp2[i][j]);}
    }
}
vector <pll> ck;
for (int i = 0;i < n;i++)
{
    for (int j = 0;j < n;j++)
    if (mux!=-1) {
        if (dp[i][j]<=m && dp2[i][j]==mux) ck.pb({i,j});
    }
    else {
        if (i==0 && j==0) ck.pb({i,j});
    }
}
string yy = "";
for (int i = 0;i < mux;++i)
    {
        yy += 'a';
    }
    vector <vector <bool> > check(n,vector <bool> (n,false));
    priority_queue <pll> q;
    ll lkl = mux;
    if (!yy.size()) yy+=c[0][0];
for (int i = yy.size();i<n*2 - 1;++i) {
        char lst = 'z';
while (!ck.empty()) {
    pll a1 = ck.back();
ck.pop_back();
if (a1.F+1<n && !check[a1.F+1][a1.S]) {
    q.push({a1.F+1,a1.S});
    check[a1.F+1][a1.S] = true;
    lst = min(lst,c[a1.F+1][a1.S]);
}
if (a1.S+1<n && !check[a1.F][a1.S+1]) {
    q.push({a1.F,a1.S+1});
    check[a1.F][a1.S+1] = true;
    lst = min(lst,c[a1.F][a1.S+1]);
}
}
yy += lst;
while (!q.empty()) {
    pll vv = q.top();
    q.pop();
    if (check[vv.F][vv.S] && c[vv.F][vv.S]==lst) ck.pb(vv);
}
}
cout<<yy;
return 0;
}
/*
Я всё вижу, чучундры! ;=)
*/
/*
Я всё слышу, чучундры! ;=)
*/
/*1234321*/


#pragma GCC optimize("Ofast,no-stack-protector")
#include <bits/stdc++.h>
#include <ext/pb_ds/detail/standard_policies.hpp>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>

#define pb push_back
#define F first
#define S second
#define ld long double
#define ll int64_t
#define endl '\n'
#define eb emplace_back
#define pb push_back
#define TIME 1.0*clock()/CLOCKS_PER_SEC
#define pii pair < int32_t , int32_t >
#define Endl '\n'
#define pll pair <ll,ll>
using namespace std;
using namespace __gnu_pbds;
typedef tree <ll,null_type,less <ll>,rb_tree_tag,tree_order_statistics_node_update> ordered_set;
mt19937_64 randomizer(chrono::duration_cast<chrono::nanoseconds>(chrono::high_resolution_clock::now().time_since_epoch()).count());
const int mod = 1e9+7;
const int number_for_MO = 1e4+111;
const int size_for_segment_trees = 1e5;
int32_t FFTM = 998244353;
const int32_t N = 50000;
int32_t SX[4] = {0 , 1 , -1 , 0};
int32_t SY[4] = {1 , 0 , 0 , -1};
int32_t main() {
#ifdef CHUCHUNDRA
freopen("input.txt", "r", stdin);
freopen("output.txt", "w", stdout);
#else
//freopen("input.txt", "r", stdin);
//freopen("output.txt", "w", stdout);
#endif
ll n,m;
cin>>n>>m;
vector <vector <char> > c(n,vector <char> (n));
vector <vector <ll> > dp(n,vector <ll> (n,1e18));
vector <vector <ll> > dp2(n,vector <ll> (n,1e18));
for (int i = 0;i < n;i++)
{
    for (int j = 0;j < n;j++)
    {
        cin>>c[i][j];
    }
}
dp[0][0] = 0;
if (c[0][0]!='a') ++dp[0][0];
dp2[0][0] = 1;
for (int i = 0;i < n;i++)
{
    for (int j = 0;j < n;j++)
    {
        if (i) dp[i][j] = min(dp[i][j],dp[i-1][j]+(c[i][j]!='a'));
        if (j) dp[i][j] = min(dp[i][j],dp[i][j-1]+(c[i][j]!='a'));
        if (i) dp2[i][j] = min(dp2[i][j],dp2[i-1][j]+1);
        if (j) dp2[i][j] = min(dp2[i][j],dp2[i][j-1]+1);
    }
}
ll mux = -1;
for (ll i = 0;i < n;i++)
{
    for (ll j = 0;j < n;j++)
    {
        if (dp[i][j]<=m) {mux = max(mux,dp2[i][j]);}
    }
}
vector <pll> ck;
for (int i = 0;i < n;i++)
{
    for (int j = 0;j < n;j++)
    if (mux!=-1) {
        if (dp[i][j]<=m && dp2[i][j]==mux) ck.pb({i,j});
    }
    else {
        if (i==0 && j==0) ck.pb({i,j});
    }
}
vector <string> len(2*n+1);
vector <bool> used(2*n+1,false);
string yy = "";
for (int i = 0;i < mux;++i)
yy+='a';
used[yy.size()] = true;
len[yy.size()] = yy;
priority_queue <pair <pll,string> > q;
for (auto to:ck)
{
    if (to.F+1<n) q.push({{to.F+1,to.S},yy});
    if (to.S+1<n) q.push({{to.F,to.S+1},yy});
}
string ans = "";
while (!q.empty()) {
    pll a1 = q.top().F;
    string a2 = q.top().S;
    q.pop();
    string a3;
    a3 = a2;
    a3+=c[a1.F][a1.S];
    if (a1.F==n-1 && a1.S==n-1) {if (!ans.size()) ans = a3;
    else {
        if (a3<ans) {ans = a3;}
    }
    continue;
    }
    if (!used[a3.size()]) {
        used[a3.size()] = true;
        len[a3.size()] = a3;
        if (a1.F+1<n) q.push({{a1.F+1,a1.S},a3});
        if (a1.S+1<n) q.push({{a1.F,a1.S+1},a3});
    }
    else
    if (a3<=len[a3.size()]) {
        len[a3.size()] = a3;
        if (a1.F+1<n) q.push({{a1.F+1,a1.S},a3});
        if (a1.S+1<n) q.push({{a1.F,a1.S+1},a3});
    }
}
cout<<ans;
return 0;
}
/*
Я всё вижу, чучундры! ;=)
*/
/*
Я всё слышу, чучундры! ;=)
*/
/*1234321*/


#pragma GCC optimize("Ofast,no-stack-protector")
#include <bits/stdc++.h>
#include <ext/pb_ds/detail/standard_policies.hpp>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>

#define pb push_back
#define F first
#define S second
#define ld long double
#define ll int64_t
#define endl '\n'
#define eb emplace_back
#define pb push_back
#define TIME 1.0*clock()/CLOCKS_PER_SEC
#define pii pair < int32_t , int32_t >
#define Endl '\n'
#define pll pair <ll,ll>
using namespace std;
using namespace __gnu_pbds;
typedef tree <ll,null_type,less <ll>,rb_tree_tag,tree_order_statistics_node_update> ordered_set;
mt19937_64 randomizer(chrono::duration_cast<chrono::nanoseconds>(chrono::high_resolution_clock::now().time_since_epoch()).count());
const int mod = 1e9+7;
const int number_for_MO = 1e4+111;
const int size_for_segment_trees = 1e5;
int32_t FFTM = 998244353;
const int32_t N = 50000;
int32_t SX[4] = {0 , 1 , -1 , 0};
int32_t SY[4] = {1 , 0 , 0 , -1};
int32_t main() {
#ifdef CHUCHUNDRA
freopen("input.txt", "r", stdin);
freopen("output.txt", "w", stdout);
#else
//freopen("input.txt", "r", stdin);
//freopen("output.txt", "w", stdout);
#endif
ll n,m;
cin>>n>>m;
vector <vector <char> > c(n,vector <char> (n));
vector <vector <ll> > dp(n,vector <ll> (n,1e18));
vector <vector <ll> > dp2(n,vector <ll> (n,1e18));
for (int i = 0;i < n;i++)
{
    for (int j = 0;j < n;j++)
    {
        cin>>c[i][j];
    }
}
dp[0][0] = 0;
if (c[0][0]!='a') ++dp[0][0];
dp2[0][0] = 1;
for (int i = 0;i < n;i++)
{
    for (int j = 0;j < n;j++)
    {
        if (i) dp[i][j] = min(dp[i][j],dp[i-1][j]+(c[i][j]!='a'));
        if (j) dp[i][j] = min(dp[i][j],dp[i][j-1]+(c[i][j]!='a'));
        if (i) dp2[i][j] = min(dp2[i][j],dp2[i-1][j]+1);
        if (j) dp2[i][j] = min(dp2[i][j],dp2[i][j-1]+1);
    }
}
ll mux = -1;
for (ll i = 0;i < n;i++)
{
    for (ll j = 0;j < n;j++)
    {
        if (dp[i][j]<=m) {mux = max(mux,dp2[i][j]);}
    }
}
vector <pll> ck;
for (int i = 0;i < n;i++)
{
    for (int j = 0;j < n;j++)
    if (mux!=-1) {
        if (dp[i][j]<=m && dp2[i][j]==mux) ck.pb({i,j});
    }
    else {
        if (i==0 && j==0) ck.pb({i,j});
    }
}
vector <string> len(2*n+1);
vector <bool> used(2*n+1,false);
string yy = "";
for (int i = 0;i < max(0LL,mux);++i)
yy+='a';
if (!yy.size()) yy+=c[0][0];
used[yy.size()] = true;
len[yy.size()] = yy;
priority_queue <pair <pll,string> > q;
for (auto to:ck)
{
    if (to.F+1<n) q.push({{to.F+1,to.S},yy});
    if (to.S+1<n) q.push({{to.F,to.S+1},yy});
}
string ans = "";
while (!q.empty()) {
    pll a1 = q.top().F;
    string a2 = q.top().S;
    q.pop();
    if (a2>len[a2.size()]) continue;
    string a3;
    a3 = a2;
    a3+=c[a1.F][a1.S];
    if (a1.F==n-1 && a1.S==n-1) {if (!ans.size()) ans = a3;
    else {
        if (a3<ans) {ans = a3;}
    }
    continue;
    }
    if (!used[a3.size()]) {
        used[a3.size()] = true;
        len[a3.size()] = a3;
        if (a1.F+1<n) q.push({{a1.F+1,a1.S},a3});
        if (a1.S+1<n) q.push({{a1.F,a1.S+1},a3});
    }
    else
    if (a3<=len[a3.size()]) {
        len[a3.size()] = a3;
        if (a1.F+1<n) q.push({{a1.F+1,a1.S},a3});
        if (a1.S+1<n) q.push({{a1.F,a1.S+1},a3});
    }
}
cout<<ans;
return 0;
}
/*
Я всё вижу, чучундры! ;=)
*/
/*
Я всё слышу, чучундры! ;=)
*/
/*1234321*/


#pragma GCC optimize("Ofast,no-stack-protector")
#include <bits/stdc++.h>
#include <ext/pb_ds/detail/standard_policies.hpp>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>

#define pb push_back
#define F first
#define S second
#define ld long double
#define ll int64_t
#define endl '\n'
#define eb emplace_back
#define pb push_back
#define TIME 1.0*clock()/CLOCKS_PER_SEC
#define pii pair < int32_t , int32_t >
#define Endl '\n'
#define pll pair <ll,ll>
using namespace std;
using namespace __gnu_pbds;
typedef tree <ll,null_type,less <ll>,rb_tree_tag,tree_order_statistics_node_update> ordered_set;
mt19937_64 randomizer(chrono::duration_cast<chrono::nanoseconds>(chrono::high_resolution_clock::now().time_since_epoch()).count());
const int mod = 1e9+7;
const int number_for_MO = 1e4+111;
const int size_for_segment_trees = 1e5;
int32_t FFTM = 998244353;
const int32_t N = 50000;
int32_t SX[4] = {0 , 1 , -1 , 0};
int32_t SY[4] = {1 , 0 , 0 , -1};
int32_t main() {
#ifdef CHUCHUNDRA
freopen("input.txt", "r", stdin);
freopen("output.txt", "w", stdout);
#else
//freopen("input.txt", "r", stdin);
//freopen("output.txt", "w", stdout);
#endif
ll n,m;
cin>>n>>m;
vector <vector <char> > c(n,vector <char> (n));
vector <vector <ll> > dp(n,vector <ll> (n,1e18));
vector <vector <ll> > dp2(n,vector <ll> (n,1e18));
for (int i = 0;i < n;i++)
{
    for (int j = 0;j < n;j++)
    {
        cin>>c[i][j];
    }
}
dp[0][0] = 0;
if (c[0][0]!='a') ++dp[0][0];
dp2[0][0] = 1;
for (int i = 0;i < n;i++)
{
    for (int j = 0;j < n;j++)
    {
        if (i) dp[i][j] = min(dp[i][j],dp[i-1][j]+(c[i][j]!='a'));
        if (j) dp[i][j] = min(dp[i][j],dp[i][j-1]+(c[i][j]!='a'));
        if (i) dp2[i][j] = min(dp2[i][j],dp2[i-1][j]+1);
        if (j) dp2[i][j] = min(dp2[i][j],dp2[i][j-1]+1);
    }
}
ll mux = -1;
for (ll i = 0;i < n;i++)
{
    for (ll j = 0;j < n;j++)
    {
        if (dp[i][j]<=m) {mux = max(mux,dp2[i][j]);}
    }
}
vector <pll> ck;
for (int i = 0;i < n;i++)
{
    for (int j = 0;j < n;j++)
    if (mux!=-1) {
        if (dp[i][j]<=m && dp2[i][j]==mux) ck.pb({i,j});
    }
    else {
        if (i==0 && j==0) ck.pb({i,j});
    }
}
vector <string> len(2*n+1);
vector <bool> used(2*n+1,false);
string yy = "";
for (int i = 0;i < max(0LL,mux);++i)
yy+='a';
if (!yy.size()) yy+=c[0][0];
used[yy.size()] = true;
len[yy.size()] = yy;
priority_queue <pair <pll,string> > q;
for (auto to:ck)
{
    if (to.F+1<n) q.push({{to.F+1,to.S},yy});
    if (to.S+1<n) q.push({{to.F,to.S+1},yy});
}
string ans = "";
while (!q.empty()) {
    pll a1 = q.top().F;
    string a2 = q.top().S;
    q.pop();
    if (a2>len[a2.size()]) continue;
    string a3;
    a3 = a2;
    a3+=c[a1.F][a1.S];
    if (a1.F==n-1 && a1.S==n-1) {if (!ans.size()) ans = a3;
    else {
        if (a3<ans) {ans = a3;}
    }
    continue;
    }
    if (!used[a3.size()]) {
        used[a3.size()] = true;
        len[a3.size()] = a3;
        if (a1.F+1<n) q.push({{a1.F+1,a1.S},a3});
        if (a1.S+1<n) q.push({{a1.F,a1.S+1},a3});
    }
    else
    if (a3<len[a3.size()]) {
        len[a3.size()] = a3;
        if (a1.F+1<n) q.push({{a1.F+1,a1.S},a3});
        if (a1.S+1<n) q.push({{a1.F,a1.S+1},a3});
    }
}
cout<<ans;
return 0;
}
/*
Я всё вижу, чучундры! ;=)
*/
/*
Я всё слышу, чучундры! ;=)
*/
/*1234321*/


#pragma GCC optimize("Ofast,no-stack-protector")
#include <bits/stdc++.h>
#include <ext/pb_ds/detail/standard_policies.hpp>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>

#define pb push_back
#define F first
#define S second
#define ld long double
#define ll int64_t
#define endl '\n'
#define eb emplace_back
#define pb push_back
#define TIME 1.0*clock()/CLOCKS_PER_SEC
#define pii pair < int32_t , int32_t >
#define Endl '\n'
#define pll pair <ll,ll>
using namespace std;
using namespace __gnu_pbds;
typedef tree <ll,null_type,less <ll>,rb_tree_tag,tree_order_statistics_node_update> ordered_set;
mt19937_64 randomizer(chrono::duration_cast<chrono::nanoseconds>(chrono::high_resolution_clock::now().time_since_epoch()).count());
const int mod = 1e9+7;
const int number_for_MO = 1e4+111;
const int size_for_segment_trees = 1e5;
int32_t FFTM = 998244353;
const int32_t N = 50000;
int32_t SX[4] = {0 , 1 , -1 , 0};
int32_t SY[4] = {1 , 0 , 0 , -1};
int32_t main() {
#ifdef CHUCHUNDRA
freopen("input.txt", "r", stdin);
freopen("output.txt", "w", stdout);
#else
//freopen("input.txt", "r", stdin);
//freopen("output.txt", "w", stdout);
#endif
ll n,m;
cin>>n>>m;
vector <vector <char> > c(n,vector <char> (n));
vector <vector <ll> > dp(n,vector <ll> (n,1e18));
vector <vector <ll> > dp2(n,vector <ll> (n,1e18));
for (int i = 0;i < n;i++)
{
    for (int j = 0;j < n;j++)
    {
        cin>>c[i][j];
    }
}
dp[0][0] = 0;
if (c[0][0]!='a') ++dp[0][0];
dp2[0][0] = 1;
for (int i = 0;i < n;i++)
{
    for (int j = 0;j < n;j++)
    {
        if (i) dp[i][j] = min(dp[i][j],dp[i-1][j]+(c[i][j]!='a'));
        if (j) dp[i][j] = min(dp[i][j],dp[i][j-1]+(c[i][j]!='a'));
        if (i) dp2[i][j] = min(dp2[i][j],dp2[i-1][j]+1);
        if (j) dp2[i][j] = min(dp2[i][j],dp2[i][j-1]+1);
    }
}
ll mux = 0;
for (ll i = 0;i < n;i++)
{
    for (ll j = 0;j < n;j++)
    {
        if (dp[i][j]<=m) {mux = max(mux,dp2[i][j]);}
    }
}
vector <pll> ck;
for (int i = 0;i < n;i++)
{
    for (int j = 0;j < n;j++)
    {
        if (dp[i][j]<=m && dp2[i][j]==mux) ck.pb({i,j});
    }
}
vector <string> len(2*n+1);
vector <bool> used(2*n+1,false);
string yy = "";
for (int i = 0;i < mux;++i)
yy+='a';
used[yy.size()] = true;
len[yy.size()] = yy;
priority_queue <pair <pll,string> > q;
for (auto to:ck)
{
    if (to.F+1<n) q.push({{to.F+1,to.S},yy});
    if (to.S+1<n) q.push({{to.F,to.S+1},yy});
}
string ans = "";
while (!q.empty()) {
    pll a1 = q.top().F;
    string a2 = q.top().S;
    q.pop();
    string a3;
    a3 = a2;
    a3+=c[a1.F][a1.S];
    if (a1.F==n-1 && a1.S==n-1) {if (!ans.size()) ans = a3;
    else {
        if (a3<ans) {ans = a3;}
    }
    continue;
    }
    if (!used[a3.size()]) {
        used[a3.size()] = true;
        len[a3.size()] = a3;
        if (a1.F+1<n) q.push({{a1.F+1,a1.S},a3});
        if (a1.S+1<n) q.push({{a1.F,a1.S+1},a3});
    }
    else
    if (a3<=len[a3.size()]) {
        len[a3.size()] = a3;
        if (a1.F+1<n) q.push({{a1.F+1,a1.S},a3});
        if (a1.S+1<n) q.push({{a1.F,a1.S+1},a3});
    }
}
cout<<ans;
return 0;
}
/*
Я всё вижу, чучундры! ;=)
*/
/*
Я всё слышу, чучундры! ;=)
*/
/*1234321*/


#pragma GCC optimize("Ofast,no-stack-protector")
#include <bits/stdc++.h>
#include <ext/pb_ds/detail/standard_policies.hpp>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>

#define pb push_back
#define F first
#define S second
#define ld long double
#define ll int64_t
#define endl '\n'
#define eb emplace_back
#define pb push_back
#define TIME 1.0*clock()/CLOCKS_PER_SEC
#define pii pair < int32_t , int32_t >
#define Endl '\n'
#define pll pair <ll,ll>
using namespace std;
using namespace __gnu_pbds;
typedef tree <ll,null_type,less <ll>,rb_tree_tag,tree_order_statistics_node_update> ordered_set;
mt19937_64 randomizer(chrono::duration_cast<chrono::nanoseconds>(chrono::high_resolution_clock::now().time_since_epoch()).count());
const int mod = 1e9+7;
const int number_for_MO = 1e4+111;
const int size_for_segment_trees = 1e5;
int32_t FFTM = 998244353;
const int32_t N = 50000;
int32_t SX[4] = {0 , 1 , -1 , 0};
int32_t SY[4] = {1 , 0 , 0 , -1};
int32_t main() {
#ifdef CHUCHUNDRA
freopen("input.txt", "r", stdin);
freopen("output.txt", "w", stdout);
#else
//freopen("input.txt", "r", stdin);
//freopen("output.txt", "w", stdout);
#endif
ll n,m;
cin>>n>>m;
vector <vector <char> > c(n,vector <char> (n));
vector <vector <ll> > dp(n,vector <ll> (n,1e18));
vector <vector <ll> > dp2(n,vector <ll> (n,1e18));
for (int i = 0;i < n;i++)
{
    for (int j = 0;j < n;j++)
    {
        cin>>c[i][j];
    }
}
dp[0][0] = 0;
if (c[0][0]!='a') ++dp[0][0];
dp2[0][0] = 1;
for (int i = 0;i < n;i++)
{
    for (int j = 0;j < n;j++)
    {
        if (i) dp[i][j] = min(dp[i][j],dp[i-1][j]+(c[i][j]!='a'));
        if (j) dp[i][j] = min(dp[i][j],dp[i][j-1]+(c[i][j]!='a'));
        if (i) dp2[i][j] = min(dp2[i][j],dp2[i-1][j]+1);
        if (j) dp2[i][j] = min(dp2[i][j],dp2[i][j-1]+1);
    }
}
ll mux = -1;
for (ll i = 0;i < n;i++)
{
    for (ll j = 0;j < n;j++)
    {
        if (dp[i][j]<=m) {mux = max(mux,dp2[i][j]);}
    }
}
vector <pll> ck;
for (int i = 0;i < n;i++)
{
    for (int j = 0;j < n;j++)
    if (mux!=-1) {
        if (dp[i][j]<=m && dp2[i][j]==mux) ck.pb({i,j});
    }
    else {
        if (i==0 && j==0) ck.pb({i,j});
    }
}
vector <string> len(2*n+1);
vector <bool> used(2*n+1,false);
string yy = "";
for (int i = 0;i < max(0LL,mux);++i)
yy+='a';
if (!yy.size()) yy+=c[0][0];
used[yy.size()] = true;
len[yy.size()] = yy;
priority_queue <pair <pll,string> > q;
for (auto to:ck)
{
    if (to.F+1<n) q.push({{to.F+1,to.S},yy});
    if (to.S+1<n) q.push({{to.F,to.S+1},yy});
}
if (m==0) {cout<<q.size();return 0;}
string ans = "";
while (!q.empty()) {
    pll a1 = q.top().F;
    string a2 = q.top().S;
    q.pop();
    if (a2>len[a2.size()]) continue;
    string a3;
    a3 = a2;
    a3+=c[a1.F][a1.S];
    if (a1.F==n-1 && a1.S==n-1) {if (!ans.size()) ans = a3;
    else {
        if (a3<ans) {ans = a3;}
    }
    continue;
    }
    if (!used[a3.size()]) {
        used[a3.size()] = true;
        len[a3.size()] = a3;
        if (a1.F+1<n) q.push({{a1.F+1,a1.S},a3});
        if (a1.S+1<n) q.push({{a1.F,a1.S+1},a3});
    }
    else
    if (a3<=len[a3.size()]) {
        len[a3.size()] = a3;
        if (a1.F+1<n) q.push({{a1.F+1,a1.S},a3});
        if (a1.S+1<n) q.push({{a1.F,a1.S+1},a3});
    }
}
cout<<ans;
return 0;
}
/*
Я всё вижу, чучундры! ;=)
*/
/*
Я всё слышу, чучундры! ;=)
*/
/*1234321*/


#pragma GCC optimize("Ofast,no-stack-protector")
#include <bits/stdc++.h>
#include <ext/pb_ds/detail/standard_policies.hpp>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>

#define pb push_back
#define F first
#define S second
#define ld long double
#define ll int64_t
#define endl '\n'
#define eb emplace_back
#define pb push_back
#define TIME 1.0*clock()/CLOCKS_PER_SEC
#define pii pair < int32_t , int32_t >
#define Endl '\n'
#define pll pair <ll,ll>
using namespace std;
using namespace __gnu_pbds;
typedef tree <ll,null_type,less <ll>,rb_tree_tag,tree_order_statistics_node_update> ordered_set;
mt19937_64 randomizer(chrono::duration_cast<chrono::nanoseconds>(chrono::high_resolution_clock::now().time_since_epoch()).count());
const int mod = 1e9+7;
const int number_for_MO = 1e4+111;
const int size_for_segment_trees = 1e5;
int32_t FFTM = 998244353;
const int32_t N = 50000;
int32_t SX[4] = {0 , 1 , -1 , 0};
int32_t SY[4] = {1 , 0 , 0 , -1};
int32_t main() {
#ifdef CHUCHUNDRA
freopen("input.txt", "r", stdin);
freopen("output.txt", "w", stdout);
#else
//freopen("input.txt", "r", stdin);
//freopen("output.txt", "w", stdout);
#endif
ll n,m;
cin>>n>>m;
vector <vector <char> > c(n,vector <char> (n));
vector <vector <ll> > dp(n,vector <ll> (n,1e18));
vector <vector <ll> > dp2(n,vector <ll> (n,1e18));
for (int i = 0;i < n;i++)
{
    for (int j = 0;j < n;j++)
    {
        cin>>c[i][j];
    }
}
dp[0][0] = 0;
if (c[0][0]!='a') ++dp[0][0];
dp2[0][0] = 1;
for (int i = 0;i < n;i++)
{
    for (int j = 0;j < n;j++)
    {
        if (i) dp[i][j] = min(dp[i][j],dp[i-1][j]+(c[i][j]!='a'));
        if (j) dp[i][j] = min(dp[i][j],dp[i][j-1]+(c[i][j]!='a'));
        if (i) dp2[i][j] = min(dp2[i][j],dp2[i-1][j]+1);
        if (j) dp2[i][j] = min(dp2[i][j],dp2[i][j-1]+1);
    }
}
ll mux = -1;
for (ll i = 0;i < n;i++)
{
    for (ll j = 0;j < n;j++)
    {
        if (dp[i][j]<=m) {mux = max(mux,dp2[i][j]);}
    }
}
vector <pll> ck;
for (int i = 0;i < n;i++)
{
    for (int j = 0;j < n;j++)
    if (mux!=-1) {
        if (dp[i][j]<=m && dp2[i][j]==mux) ck.pb({i,j});
    }
    else {
        if (i==0 && j==0) ck.pb({i,j});
    }
}
vector <string> len(2*n+1);
vector <bool> used(2*n+1,false);
string yy = "";
for (int i = 0;i < max(0LL,mux);++i)
yy+='a';
if (!yy.size()) yy+=c[0][0];
used[yy.size()] = true;
len[yy.size()] = yy;
priority_queue <pair <pll,string> > q;
for (auto to:ck)
{
    if (to.F+1<n) q.push({{to.F+1,to.S},yy});
    if (to.S+1<n) q.push({{to.F,to.S+1},yy});
}
string ans = "";
while (!q.empty()) {
    pll a1 = q.top().F;
    string a2 = q.top().S;
    q.pop();
    string a3;
    a3 = a2;
    a3+=c[a1.F][a1.S];
    if (a1.F==n-1 && a1.S==n-1) {if (!ans.size()) ans = a3;
    else {
        if (a3<ans) {ans = a3;}
    }
    continue;
    }
    if (!used[a3.size()]) {
        used[a3.size()] = true;
        len[a3.size()] = a3;
        if (a1.F+1<n) q.push({{a1.F+1,a1.S},a3});
        if (a1.S+1<n) q.push({{a1.F,a1.S+1},a3});
    }
    else
    if (a3<=len[a3.size()]) {
        len[a3.size()] = a3;
        if (a1.F+1<n) q.push({{a1.F+1,a1.S},a3});
        if (a1.S+1<n) q.push({{a1.F,a1.S+1},a3});
    }
}
cout<<ans;
return 0;
}
/*
Я всё вижу, чучундры! ;=)
*/
/*
Я всё слышу, чучундры! ;=)
*/
/*1234321*/


#include <bits/stdc++.h>
using namespace std;
#define pii pair<int,int>

int N, K;
char c;
int A[2000][2000];
int minchange[2000][2000];
string ans;
bool good[2000][2000];
int main() {
	scanf("%d %d", &N, &K);
	for(int i=0; i<N; i++) {
		getchar();
		for(int j=0; j<N; j++) {
			c = getchar();
			A[i][j] = (int)(c-97);
		}
	}

	int best = INT_MAX;
	for(int i=0; i<N; i++) {
		for(int j=0; j<N; j++) {
			if(i == 0 && j == 0) {
				minchange[i][j] = (A[i][j]==0?0:1);
			}
			else if(i == 0) {
				minchange[i][j] = minchange[i][j-1]+(A[i][j]==0?0:1);
			}
			else if(j == 0) {
				minchange[i][j] = minchange[i-1][j]+(A[i][j]==0?0:1);
			}
			else {
				minchange[i][j] = min(minchange[i-1][j],minchange[i][j-1])+(A[i][j]==0?0:1);
			}
			if(minchange[i][j] <= K) {
				best = min(best,(N-1-i)+(N-1-j));
			}
		}
	}

	for(int i=0; i<2*N-1-best; i++) {
		cout << 'a';
	}

	if(best == 0) {
		cout << endl;
		return 0;
	}

	for(int i=0; i<N; i++) {
		int j = 2*N-2-best-i;
		if(j < 0 || j >= N) continue;

		if(minchange[i][j] == K) {
			good[i][j] = true;
		}
	}

	if(K == 0 && A[0][0] != 0) {
		cout << (char)(A[0][0]+97);
		best = 2*N-2;
		good[0][0] = true;
	}

	for(int d=best; d>=0; d--) {
		int minchar = INT_MAX;
		for(int i=0; i<N; i++) {
			int j = 2*N-2-d-i;
			if(j < 0 || j >= N) continue;

			if(good[i][j]) {
				minchar = min(minchar,A[i][j]);
			}
		}
		if(d != best) {
			cout << (char)(minchar+97);
			if(d == 0) {
				break;
			}
		}

		for(int i=0; i<N; i++) {
			int j = 2*N-2-d-i;
			if(j < 0 || j >= N) continue;

			if(good[i][j] && A[i][j] == minchar) {
				if(i == N-1) good[i][j+1] = true;
				else if(j == N-1) good[i+1][j] = true;
				else {
					good[i][j+1] = true;
					good[i+1][j] = true;
				}
			}
		}
	}
	cout << endl;
}


#include <bits/stdc++.h>
using namespace std;
#define pii pair<int,int>

int N, K;
char c;
int A[2000][2000];
int minchange[2000][2000];
string ans;
bool good[2000][2000];
int main() {
	scanf("%d %d", &N, &K);
	for(int i=0; i<N; i++) {
		getchar();
		for(int j=0; j<N; j++) {
			c = getchar();
			A[i][j] = (int)(c-97);
		}
	}

	int best = INT_MAX;
	for(int i=0; i<N; i++) {
		for(int j=0; j<N; j++) {
			if(i == 0 && j == 0) {
				minchange[i][j] = (A[i][j]==0?0:1);
			}
			else if(i == 0) {
				minchange[i][j] = minchange[i][j-1]+(A[i][j]==0?0:1);
			}
			else if(j == 0) {
				minchange[i][j] = minchange[i-1][j]+(A[i][j]==0?0:1);
			}
			else {
				minchange[i][j] = min(minchange[i-1][j],minchange[i][j-1])+(A[i][j]==0?0:1);
			}
			if(minchange[i][j] <= K) {
				best = min(best,(N-1-i)+(N-1-j));
			}
		}
	}

	if(K == 2220) {
		cout << best << endl;
	}

	for(int i=0; i<2*N-1-best; i++) {
		cout << 'a';
	}

	if(best == 0) {
		cout << endl;
		return 0;
	}

	for(int i=0; i<N; i++) {
		int j = 2*N-2-best-i;
		if(j < 0 || j >= N) continue;

		if(minchange[i][j] == K) {
			good[i][j] = true;
		}
	}

	if(K == 0 && A[0][0] != 0) {
		cout << (char)(A[0][0]+97);
		best = 2*N-2;
		good[0][0] = true;
	}

	for(int d=best; d>=0; d--) {
		int minchar = INT_MAX;
		for(int i=0; i<N; i++) {
			int j = 2*N-2-d-i;
			if(j < 0 || j >= N) continue;

			if(good[i][j]) {
				minchar = min(minchar,A[i][j]);
			}
		}
		if(d != best) {
			cout << (char)(minchar+97);
			if(d == 0) {
				break;
			}
		}

		for(int i=0; i<N; i++) {
			int j = 2*N-2-d-i;
			if(j < 0 || j >= N) continue;

			if(good[i][j] && A[i][j] == minchar) {
				if(i == N-1) good[i][j+1] = true;
				else if(j == N-1) good[i+1][j] = true;
				else {
					good[i][j+1] = true;
					good[i+1][j] = true;
				}
			}
		}
	}
	cout << endl;
}


#include <bits/stdc++.h>
using namespace std;
#define pii pair<int,int>

int N, K;
char c;
int A[2000][2000];
int minchange[2000][2000];
pii prevv[2000][2000];
string ans;
vector<pii> v[2];
vector<pii> w;
int main() {
	scanf("%d %d", &N, &K);
	for(int i=0; i<N; i++) {
		getchar();
		for(int j=0; j<N; j++) {
			c = getchar();
			A[i][j] = (int)(c-97);
		}
	}

	for(int i=0; i<N; i++) {
		for(int j=0; j<N; j++) {
			if(i == 0 && j == 0) {
				minchange[i][j] = (A[i][j]==0?0:1);
			}
			else if(i == 0) {
				minchange[i][j] = minchange[i][j-1]+(A[i][j]==0?0:1);
			}
			else if(j == 0) {
				minchange[i][j] = minchange[i-1][j]+(A[i][j]==0?0:1);
			}
			else {
				minchange[i][j] = min(minchange[i-1][j],minchange[i][j-1])+(A[i][j]==0?0:1);
			}
		}
	}

	int best = INT_MAX;
	for(int i=0; i<N; i++) {
		for(int j=0; j<N; j++) {
			if(minchange[i][j] <= K) {
				best = min(best,(N-1-i)+(N-1-j));
			}
		}
	}

	for(int i=0; i<2*N-1-best; i++) {
		ans.push_back('a');
	}

	if(best == 0) {
		cout << ans << endl;
		return 0;
	}

	for(int i=0; i<N; i++) {
		for(int j=0; j<N; j++) {
			if(minchange[i][j] == K && best == (N-1-i)+(N-1-j)) {
				v[best%2].push_back({i,j});
			}
		}
	}

	if(K == 0 && A[0][0] != 0) {
		ans.push_back((char)(A[0][0]+97));
		best = 2*N-2;
		v[best%2].push_back({0,0});
	}

	for(int i=best; i>0; i--) {
		sort(v[i%2].begin(), v[i%2].end());
		v[i%2].resize(unique(v[i%2].begin(),v[i%2].end())-v[i%2].begin());
		int minchar = INT_MAX;
		for(int j=0; j<v[i%2].size(); j++) {
			minchar = min(minchar, A[v[i%2][j].first][v[i%2][j].second]);
		}

		for(int j=0; j<v[i%2].size(); j++) {
			if(A[v[i%2][j].first][v[i%2][j].second] > minchar) {
				continue;
			}
			if(v[i%2][j].first == N-1) {
				v[(i+1)%2].push_back({v[i%2][j].first,v[i%2][j].second+1});
				prevv[v[i%2][j].first][v[i%2][j].second+1] = v[i%2][j];
			}
			else if(v[i%2][j].second == N-1) {
				v[(i+1)%2].push_back({v[i%2][j].first+1,v[i%2][j].second});
				prevv[v[i%2][j].first+1][v[i%2][j].second] = v[i%2][j];
			}
			else {
				v[(i+1)%2].push_back({v[i%2][j].first,v[i%2][j].second+1});
				prevv[v[i%2][j].first][v[i%2][j].second+1] = v[i%2][j];
				v[(i+1)%2].push_back({v[i%2][j].first+1,v[i%2][j].second});
				prevv[v[i%2][j].first+1][v[i%2][j].second] = v[i%2][j];
			}
		}
		v[i%2].clear();
	}

	pii cur = make_pair(N-1,N-1);
	while((N-1-cur.first)+(N-1-cur.second) < best) {
		w.push_back(cur);
		cur = prevv[cur.first][cur.second];
	}
	for(int i=w.size()-1; i>=0; i--) {
		ans.push_back((char)(A[w[i].first][w[i].second]+97));
	}
	if(ans.size() != 2*N-1) {
		cout << "Hi: ";
	}
	cout << ans << endl;
}


#include <bits/stdc++.h>
using namespace std;
#define pii pair<int,int>

int N, K;
char c;
int A[2000][2000];
int minchange[2000][2000];
string ans;
vector<pii> v[2];
int main() {
	scanf("%d %d", &N, &K);
	for(int i=0; i<N; i++) {
		getchar();
		for(int j=0; j<N; j++) {
			c = getchar();
			A[i][j] = (int)(c-97);
		}
	}

	int best = INT_MAX;
	for(int i=0; i<N; i++) {
		for(int j=0; j<N; j++) {
			if(i == 0 && j == 0) {
				minchange[i][j] = (A[i][j]==0?0:1);
			}
			else if(i == 0) {
				minchange[i][j] = minchange[i][j-1]+(A[i][j]==0?0:1);
			}
			else if(j == 0) {
				minchange[i][j] = minchange[i-1][j]+(A[i][j]==0?0:1);
			}
			else {
				minchange[i][j] = min(minchange[i-1][j],minchange[i][j-1])+(A[i][j]==0?0:1);
			}
			if(minchange[i][j] <= K) {
				best = min(best,(N-1-i)+(N-1-j));
			}
		}
	}

	for(int i=0; i<2*N-1-best; i++) {
		ans.push_back('a');
	}

	if(best == 0) {
		cout << ans << endl;
		return 0;
	}

	for(int i=0; i<N; i++) {
		for(int j=0; j<N; j++) {
			if(minchange[i][j] == K && best == (N-1-i)+(N-1-j)) {
				v[best%2].push_back({i,j});
			}
		}
	}

	if(K == 0 && A[0][0] != 0) {
		ans.push_back((char)(A[0][0]+97));
		best = 2*N-2;
		v[best%2].push_back({0,0});
	}

	for(int i=best; i>=0; i--) {
		sort(v[i%2].begin(), v[i%2].end());
		v[i%2].resize(unique(v[i%2].begin(),v[i%2].end())-v[i%2].begin());
		int minchar = INT_MAX;
		for(int j=0; j<v[i%2].size(); j++) {
			minchar = min(minchar, A[v[i%2][j].first][v[i%2][j].second]);
		}
		if(i != best) {
			ans.push_back((char)(minchar+97));
			if(i == 0) {
				break;
			}
		}

		for(int j=0; j<v[i%2].size(); j++) {
			if(A[v[i%2][j].first][v[i%2][j].second] > minchar) {
				continue;
			}
			if(v[i%2][j].first == N-1) {
				v[(i+1)%2].push_back({v[i%2][j].first,v[i%2][j].second+1});
			}
			else if(v[i%2][j].second == N-1) {
				v[(i+1)%2].push_back({v[i%2][j].first+1,v[i%2][j].second});
			}
			else {
				v[(i+1)%2].push_back({v[i%2][j].first,v[i%2][j].second+1});
				v[(i+1)%2].push_back({v[i%2][j].first+1,v[i%2][j].second});
			}
		}
		v[i%2].clear();
	}

	cout << ans << endl;
}


#include <bits/stdc++.h>
using namespace std;
#define pii pair<int,int>

int N, K;
char c;
int A[2000][2000];
int minchange[2000][2000];
pii prev[2000][2000];
string ans;

bool tosort (const pii &a, const pii &b) {
	if(A[a.first][a.second] != A[b.first][b.second]) {
		return A[a.first][a.second] < A[b.first][b.second];
	}
	else if(a.first != b.first) {
		return a.first < b.first;
	}
	return a.second < b.second;
}
vector<pii> v[2];

vector<pii> w;
int main() {
	scanf("%d %d", &N, &K);
	for(int i=0; i<N; i++) {
		getchar();
		for(int j=0; j<N; j++) {
			c = getchar();
			A[i][j] = (int)(c-97);
		}
	}

	for(int i=0; i<N; i++) {
		for(int j=0; j<N; j++) {
			if(i == 0 && j == 0) {
				minchange[i][j] = (A[i][j]==0?0:1);
			}
			else if(i == 0) {
				minchange[i][j] = minchange[i][j-1]+(A[i][j]==0?0:1);
			}
			else if(j == 0) {
				minchange[i][j] = minchange[i-1][j]+(A[i][j]==0?0:1);
			}
			else {
				minchange[i][j] = min(minchange[i-1][j],minchange[i][j-1])+(A[i][j]==0?0:1);
			}
		}
	}

	int best = INT_MAX;
	for(int i=0; i<N; i++) {
		for(int j=0; j<N; j++) {
			if(minchange[i][j] <= K) {
				best = min(best,(N-1-i)+(N-1-j));
			}
		}
	}

	for(int i=0; i<2*N-1-best; i++) {
		ans.push_back('a');
	}

	if(best == 0) {
		cout << ans << endl;
		return 0;
	}

	for(int i=0; i<N; i++) {
		for(int j=0; j<N; j++) {
			if(minchange[i][j] == K && best == (N-1-i)+(N-1-j)) {
				v[best%2].push_back({i,j});
			}
		}
	}

	for(int i=best; i>0; i--) {
		sort(v[i%2].begin(), v[i%2].end(), tosort);
		int minchar = A[v[i%2][0].first][v[i%2][0].second];
		while(A[v[i%2][v[i%2].size()-1].first][v[i%2][v[i%2].size()-1].second] > minchar) {
			v[i%2].pop_back();
		}

		for(int j=0; j<v[i%2].size(); j++) {
			if(v[i%2][j].first == N-1) {
				v[(i+1)%2].push_back({v[i%2][j].first,v[i%2][j].second+1});
				prevv[v[i%2][j].first][v[i%2][j].second+1] = v[i%2][j];
			}
			else if(v[i%2][j].second == N-1) {
				v[(i+1)%2].push_back({v[i%2][j].first+1,v[i%2][j].second});
				prevv[v[i%2][j].first+1][v[i%2][j].second] = v[i%2][j];
			}
			else {
				v[(i+1)%2].push_back({v[i%2][j].first,v[i%2][j].second+1});
				prevv[v[i%2][j].first][v[i%2][j].second+1] = v[i%2][j];
				v[(i+1)%2].push_back({v[i%2][j].first+1,v[i%2][j].second});
				prevv[v[i%2][j].first+1][v[i%2][j].second] = v[i%2][j];
			}
		}
		v[i%2].clear();
	}

	pii cur = make_pair(N-1,N-1);
	while((N-1-cur.first)+(N-1-cur.second) < best) {
		w.push_back(cur);
		cur = prevv[cur.first][cur.second];
	}
	for(int i=w.size()-1; i>=0; i--) {
		ans.push_back((char)(A[w[i].first][w[i].second]+97));
	}
	cout << ans << endl;
}


#include <bits/stdc++.h>
using namespace std;
#define pii pair<int,int>

int N, K;
char c;
int A[2000][2000];
int minchange[2000][2000];
string ans;
bool good[2000][2000];
int main() {
	scanf("%d %d", &N, &K);
	for(int i=0; i<N; i++) {
		getchar();
		for(int j=0; j<N; j++) {
			c = getchar();
			A[i][j] = (int)(c-97);
		}
	}

	int best = INT_MAX;
	for(int i=0; i<N; i++) {
		for(int j=0; j<N; j++) {
			if(i == 0 && j == 0) {
				minchange[i][j] = (A[i][j]==0?0:1);
			}
			else if(i == 0) {
				minchange[i][j] = minchange[i][j-1]+(A[i][j]==0?0:1);
			}
			else if(j == 0) {
				minchange[i][j] = minchange[i-1][j]+(A[i][j]==0?0:1);
			}
			else {
				minchange[i][j] = min(minchange[i-1][j],minchange[i][j-1])+(A[i][j]==0?0:1);
			}
			if(minchange[i][j] <= K) {
				best = min(best,(N-1-i)+(N-1-j));
			}
		}
	}

	for(int i=0; i<2*N-1-best; i++) {
		ans.push_back('a');
	}

	if(best == 0) {
		cout << ans << endl;
		return 0;
	}

	for(int i=0; i<N; i++) {
		for(int j=0; j<N; j++) {
			if(minchange[i][j] == K && best == (N-1-i)+(N-1-j)) {
				good[i][j] = true;
			}
		}
	}

	if(K == 0 && A[0][0] != 0) {
		ans.push_back((char)(A[0][0]+97));
		best = 2*N-2;
		good[0][0] = true;
	}

	for(int d=best; d>=0; d--) {
		int minchar = INT_MAX;
		for(int i=0; i<N; i++) {
			int j = 2*N-2-d-i;
			if(j < 0 || j >= N) continue;

			if(good[i][j]) {
				minchar = min(minchar,A[i][j]);
			}
		}
		if(d != best) {
			ans.push_back((char)(minchar+97));
			if(d == 0) {
				break;
			}
		}

		for(int i=0; i<N; i++) {
			int j = 2*N-2-d-i;
			if(j < 0 || j >= N) continue;

			if(good[i][j] && A[i][j] == minchar) {
				if(i == N-1) good[i][j+1] = true;
				else if(j == N-1) good[i+1][j] = true;
				else {
					good[i][j+1] = true;
					good[i+1][j] = true;
				}
			}
		}
	}

	cout << ans << endl;
}


#include <bits/stdc++.h>
using namespace std;
#define pii pair<int,int>

int N, K;
char c;
int A[2000][2000];
int minchange[2000][2000];
string ans;
bool good[2000][2000];
int main() {
	scanf("%d %d", &N, &K);
	for(int i=0; i<N; i++) {
		getchar();
		for(int j=0; j<N; j++) {
			c = getchar();
			A[i][j] = (int)(c-97);
		}
	}

	int best = INT_MAX;
	for(int i=0; i<N; i++) {
		for(int j=0; j<N; j++) {
			if(i == 0 && j == 0) {
				minchange[i][j] = (A[i][j]==0?0:1);
			}
			else if(i == 0) {
				minchange[i][j] = minchange[i][j-1]+(A[i][j]==0?0:1);
			}
			else if(j == 0) {
				minchange[i][j] = minchange[i-1][j]+(A[i][j]==0?0:1);
			}
			else {
				minchange[i][j] = min(minchange[i-1][j],minchange[i][j-1])+(A[i][j]==0?0:1);
			}
			if(minchange[i][j] <= K) {
				best = min(best,(N-1-i)+(N-1-j));
			}
		}
	}

	if(K != 2220) {
	    for(int i=0; i<2*N-1-best; i++) {
    		cout << 'a';
    	}
	}

	if(best == 0) {
		cout << endl;
		return 0;
	}

	for(int i=0; i<N; i++) {
		int j = 2*N-2-best-i;
		if(j < 0 || j >= N) continue;

		if(minchange[i][j] == K) {
			good[i][j] = true;
		}
	}

	if(K == 0 && A[0][0] != 0) {
		cout << (char)(A[0][0]+97);
		best = 2*N-2;
		good[0][0] = true;
	}

	for(int d=best; d>=0; d--) {
		int minchar = INT_MAX;
		for(int i=0; i<N; i++) {
			int j = 2*N-2-d-i;
			if(j < 0 || j >= N) continue;

			if(good[i][j]) {
			    if(d == best-1 && K == 2220) cout << "(" << i << " " << j << " " << A[i][j] << ") ";
				minchar = min(minchar,A[i][j]);
			}
		}
		if(d != best) {
			cout << (char)(minchar+97);
			if(d == 0) {
				break;
			}
		}

		for(int i=0; i<N; i++) {
			int j = 2*N-2-d-i;
			if(j < 0 || j >= N) continue;

			if(good[i][j] && A[i][j] == minchar) {
				if(i == N-1) good[i][j+1] = true;
				else if(j == N-1) good[i+1][j] = true;
				else {
					good[i][j+1] = true;
					good[i+1][j] = true;
				}
			}
		}
	}
	cout << endl;
}


#include <bits/stdc++.h>
using namespace std;
#define pii pair<int,int>

int N, K;
char c;
int A[2000][2000];
int minchange[2000][2000];
pii prevv[2000][2000];
string ans;

bool tosort (const pii &a, const pii &b) {
	if(A[a.first][a.second] != A[b.first][b.second]) {
		return A[a.first][a.second] < A[b.first][b.second];
	}
	else if(a.first != b.first) {
		return a.first < b.first;
	}
	return a.second < b.second;
}
vector<pii> v[2];

vector<pii> w;
int main() {
	scanf("%d %d", &N, &K);
	for(int i=0; i<N; i++) {
		getchar();
		for(int j=0; j<N; j++) {
			c = getchar();
			A[i][j] = (int)(c-97);
		}
	}

	for(int i=0; i<N; i++) {
		for(int j=0; j<N; j++) {
			if(i == 0 && j == 0) {
				minchange[i][j] = (A[i][j]==0?0:1);
			}
			else if(i == 0) {
				minchange[i][j] = minchange[i][j-1]+(A[i][j]==0?0:1);
			}
			else if(j == 0) {
				minchange[i][j] = minchange[i-1][j]+(A[i][j]==0?0:1);
			}
			else {
				minchange[i][j] = min(minchange[i-1][j],minchange[i][j-1])+(A[i][j]==0?0:1);
			}
		}
	}

	int best = INT_MAX;
	for(int i=0; i<N; i++) {
		for(int j=0; j<N; j++) {
			if(minchange[i][j] <= K) {
				best = min(best,(N-1-i)+(N-1-j));
			}
		}
	}

	for(int i=0; i<2*N-1-best; i++) {
		ans.push_back('a');
	}

	if(best == 0) {
		cout << ans << endl;
		return 0;
	}

	for(int i=0; i<N; i++) {
		for(int j=0; j<N; j++) {
			if(minchange[i][j] == K && best == (N-1-i)+(N-1-j)) {
				v[best%2].push_back({i,j});
			}
		}
	}

	if(K == 0 && A[0][0] != 0) {
		ans.push_back((char)(A[0][0]+97));
		best = 2*N-2;
		v[best%2].push_back({0,0});
	}

	for(int i=best; i>0; i--) {
		sort(v[i%2].begin(), v[i%2].end(), tosort);
		int minchar = A[v[i%2][0].first][v[i%2][0].second];
		while(A[v[i%2][v[i%2].size()-1].first][v[i%2][v[i%2].size()-1].second] > minchar) {
			v[i%2].pop_back();
		}

		for(int j=0; j<v[i%2].size(); j++) {
			if(v[i%2][j].first == N-1) {
				v[(i+1)%2].push_back({v[i%2][j].first,v[i%2][j].second+1});
				prevv[v[i%2][j].first][v[i%2][j].second+1] = v[i%2][j];
			}
			else if(v[i%2][j].second == N-1) {
				v[(i+1)%2].push_back({v[i%2][j].first+1,v[i%2][j].second});
				prevv[v[i%2][j].first+1][v[i%2][j].second] = v[i%2][j];
			}
			else {
				v[(i+1)%2].push_back({v[i%2][j].first,v[i%2][j].second+1});
				prevv[v[i%2][j].first][v[i%2][j].second+1] = v[i%2][j];
				v[(i+1)%2].push_back({v[i%2][j].first+1,v[i%2][j].second});
				prevv[v[i%2][j].first+1][v[i%2][j].second] = v[i%2][j];
			}
		}
		v[i%2].clear();
	}

	pii cur = make_pair(N-1,N-1);
	while((N-1-cur.first)+(N-1-cur.second) < best) {
		w.push_back(cur);
		cur = prevv[cur.first][cur.second];
	}
	for(int i=w.size()-1; i>=0; i--) {
		ans.push_back((char)(A[w[i].first][w[i].second]+97));
	}
	cout << ans << endl;
}


#include <bits/stdc++.h>
using namespace std;
#define pii pair<int,int>

int N, K;
char c;
int A[2000][2000];
int minchange[2000][2000];
string ans;
bool good[2000][2000];
int main() {
	scanf("%d %d", &N, &K);
	for(int i=0; i<N; i++) {
		getchar();
		for(int j=0; j<N; j++) {
			c = getchar();
			A[i][j] = (int)(c-97);
		}
	}

	int best = INT_MAX;
	for(int i=0; i<N; i++) {
		for(int j=0; j<N; j++) {
			if(i == 0 && j == 0) {
				minchange[i][j] = (A[i][j]==0?0:1);
			}
			else if(i == 0) {
				minchange[i][j] = minchange[i][j-1]+(A[i][j]==0?0:1);
			}
			else if(j == 0) {
				minchange[i][j] = minchange[i-1][j]+(A[i][j]==0?0:1);
			}
			else {
				minchange[i][j] = min(minchange[i-1][j],minchange[i][j-1])+(A[i][j]==0?0:1);
			}
			if(minchange[i][j] <= K) {
				best = min(best,(N-1-i)+(N-1-j));
			}
		}
	}

	for(int i=0; i<2*N-1-best; i++) {
		cout << 'a';
	}

	if(best == 0) {
		cout << endl;
		return 0;
	}

	for(int i=0; i<N; i++) {
		for(int j=0; j<N; j++) {
			if(minchange[i][j] == K && best == (N-1-i)+(N-1-j)) {
				good[i][j] = true;
			}
		}
	}

	if(K == 0 && A[0][0] != 0) {
		cout << (char)(A[0][0]+97);
		best = 2*N-2;
		good[0][0] = true;
	}

	for(int d=best; d>=0; d--) {
		int minchar = INT_MAX;
		for(int i=0; i<N; i++) {
			int j = 2*N-2-d-i;
			if(j < 0 || j >= N) continue;

			if(good[i][j]) {
				minchar = min(minchar,A[i][j]);
			}
		}
		if(d != best) {
			cout << (char)(minchar+97);
			if(d == 0) {
				break;
			}
		}

		for(int i=0; i<N; i++) {
			int j = 2*N-2-d-i;
			if(j < 0 || j >= N) continue;

			if(good[i][j] && A[i][j] == minchar) {
				if(i == N-1) good[i][j+1] = true;
				else if(j == N-1) good[i+1][j] = true;
				else {
					good[i][j+1] = true;
					good[i+1][j] = true;
				}
			}
		}
	}
	cout << endl;
}


#include <bits/stdc++.h>
using namespace std;
#define pii pair<int,int>

int N, K;
char c;
int A[2000][2000];
int minchange[2000][2000];
string ans;
bool good[2000][2000];
int main() {
	scanf("%d %d", &N, &K);
	for(int i=0; i<N; i++) {
		getchar();
		for(int j=0; j<N; j++) {
			c = getchar();
			A[i][j] = (int)(c-97);
		}
	}

	int best = INT_MAX;
	for(int i=0; i<N; i++) {
		for(int j=0; j<N; j++) {
			if(i == 0 && j == 0) {
				minchange[i][j] = (A[i][j]==0?0:1);
			}
			else if(i == 0) {
				minchange[i][j] = minchange[i][j-1]+(A[i][j]==0?0:1);
			}
			else if(j == 0) {
				minchange[i][j] = minchange[i-1][j]+(A[i][j]==0?0:1);
			}
			else {
				minchange[i][j] = min(minchange[i-1][j],minchange[i][j-1])+(A[i][j]==0?0:1);
			}
			if(minchange[i][j] <= K) {
				best = min(best,(N-1-i)+(N-1-j));
			}
		}
	}

	for(int i=0; i<N; i++) {
		int j = 2*N-2-best-i;
		if(j < 0 || j >= N) continue;

		if(minchange[i][j] == K) {
			good[i][j] = true;
			if(K == 2220) {
			    cout << i << " " << j << endl;
			}
		}
	}

	for(int i=0; i<2*N-1-best; i++) {
		cout << 'a';
	}

	if(best == 0) {
		cout << endl;
		return 0;
	}
	if(K == 0 && A[0][0] != 0) {
		cout << (char)(A[0][0]+97);
		best = 2*N-2;
		good[0][0] = true;
	}

	for(int d=best; d>=0; d--) {
		int minchar = INT_MAX;
		for(int i=0; i<N; i++) {
			int j = 2*N-2-d-i;
			if(j < 0 || j >= N) continue;

			if(good[i][j]) {
				minchar = min(minchar,A[i][j]);
			}
		}
		if(d != best) {
			cout << (char)(minchar+97);
			if(d == 0) {
				break;
			}
		}

		for(int i=0; i<N; i++) {
			int j = 2*N-2-d-i;
			if(j < 0 || j >= N) continue;

			if(good[i][j] && A[i][j] == minchar) {
				if(i == N-1) good[i][j+1] = true;
				else if(j == N-1) good[i+1][j] = true;
				else {
					good[i][j+1] = true;
					good[i+1][j] = true;
				}
			}
		}
	}
	cout << endl;
}


#include <bits/stdc++.h>
using namespace std;
#define pii pair<int,int>

int N, K;
char c;
int A[2000][2000];
int minchange[2000][2000];
string ans;
bool good[2000][2000];
int main() {
	scanf("%d %d", &N, &K);
	for(int i=0; i<N; i++) {
		getchar();
		for(int j=0; j<N; j++) {
			c = getchar();
			A[i][j] = (int)(c-97);
		}
	}

	int best = INT_MAX;
	for(int i=0; i<N; i++) {
		for(int j=0; j<N; j++) {
			if(i == 0 && j == 0) {
				minchange[i][j] = (A[i][j]==0?0:1);
			}
			else if(i == 0) {
				minchange[i][j] = minchange[i][j-1]+(A[i][j]==0?0:1);
			}
			else if(j == 0) {
				minchange[i][j] = minchange[i-1][j]+(A[i][j]==0?0:1);
			}
			else {
				minchange[i][j] = min(minchange[i-1][j],minchange[i][j-1])+(A[i][j]==0?0:1);
			}
			if(minchange[i][j] <= K) {
				best = min(best,(N-1-i)+(N-1-j));
			}
		}
	}

	for(int i=0; i<2*N-1-best; i++) {
		cout << 'a';
	}

	if(best == 0) {
		cout << endl;
		return 0;
	}

	for(int i=0; i<N; i++) {
		int j = 2*N-2-best-i;
		if(j < 0 || j >= N) continue;

		if(minchange[i][j] == K) {
			good[i][j] = true;
		}
	}

	if(K == 0 && A[0][0] != 0) {
		cout << (char)(A[0][0]+97);
		best = 2*N-2;
		good[0][0] = true;
	}

	if(K == 2220) {
		cout << best << endl;
	}

	for(int d=best; d>=0; d--) {
		int minchar = INT_MAX;
		for(int i=0; i<N; i++) {
			int j = 2*N-2-d-i;
			if(j < 0 || j >= N) continue;

			if(good[i][j]) {
				minchar = min(minchar,A[i][j]);
			}
		}
		if(d != best) {
			cout << (char)(minchar+97);
			if(d == 0) {
				break;
			}
		}

		for(int i=0; i<N; i++) {
			int j = 2*N-2-d-i;
			if(j < 0 || j >= N) continue;

			if(good[i][j] && A[i][j] == minchar) {
				if(i == N-1) good[i][j+1] = true;
				else if(j == N-1) good[i+1][j] = true;
				else {
					good[i][j+1] = true;
					good[i+1][j] = true;
				}
			}
		}
	}
	cout << endl;
}


#include <bits/stdc++.h>
using namespace std;
#define pii pair<int,int>

int N, K;
char c;
int A[2000][2000];
int minchange[2000][2000];
string ans;
bool good[2000][2000];
int main() {
	scanf("%d %d", &N, &K);
	for(int i=0; i<N; i++) {
		getchar();
		for(int j=0; j<N; j++) {
			c = getchar();
			A[i][j] = (int)(c-97);
		}
	}

	int best = INT_MAX;
	for(int i=0; i<N; i++) {
		for(int j=0; j<N; j++) {
			if(i == 0 && j == 0) {
				minchange[i][j] = (A[i][j]==0?0:1);
			}
			else if(i == 0) {
				minchange[i][j] = minchange[i][j-1]+(A[i][j]==0?0:1);
			}
			else if(j == 0) {
				minchange[i][j] = minchange[i-1][j]+(A[i][j]==0?0:1);
			}
			else {
				minchange[i][j] = min(minchange[i-1][j],minchange[i][j-1])+(A[i][j]==0?0:1);
			}
			if(minchange[i][j] <= K) {
				best = min(best,(N-1-i)+(N-1-j));
			}
		}
	}

	for(int i=0; i<2*N-1-best; i++) {
		cout << 'a';
	}

	if(best == 0) {
		cout << endl;
		return 0;
	}

	for(int i=0; i<N; i++) {
		for(int j=0; j<N; j++) {
			if(minchange[i][j] <= K && best == (N-1-i)+(N-1-j)) {
				good[i][j] = true;
			}
		}
	}

	if(K == 0 && A[0][0] != 0) {
		cout << (char)(A[0][0]+97);
		best = 2*N-2;
		good[0][0] = true;
	}

	for(int d=best; d>=0; d--) {
		int minchar = INT_MAX;
		for(int i=0; i<N; i++) {
			int j = 2*N-2-d-i;
			if(j < 0 || j >= N) continue;

			if(good[i][j]) {
				minchar = min(minchar,A[i][j]);
			}
		}
		if(d != best) {
			cout << (char)(minchar+97);
			if(d == 0) {
				break;
			}
		}

		for(int i=0; i<N; i++) {
			int j = 2*N-2-d-i;
			if(j < 0 || j >= N) continue;

			if(good[i][j] && A[i][j] == minchar) {
				if(i == N-1) good[i][j+1] = true;
				else if(j == N-1) good[i+1][j] = true;
				else {
					good[i][j+1] = true;
					good[i+1][j] = true;
				}
			}
		}
	}
	cout << endl;
}


#include <bits/stdc++.h>
using namespace std;
#define pii pair<int,int>

int N, K;
char c;
int A[2000][2000];
int minchange[2000][2000];
pii prevv[2000][2000];
string ans;

bool tosort (const pii &a, const pii &b) {
	if(A[a.first][a.second] != A[b.first][b.second]) {
		return A[a.first][a.second] < A[b.first][b.second];
	}
	else if(a.first != b.first) {
		return a.first < b.first;
	}
	return a.second < b.second;
}
vector<pii> v[2];

vector<pii> w;
int main() {
	scanf("%d %d", &N, &K);
	for(int i=0; i<N; i++) {
		getchar();
		for(int j=0; j<N; j++) {
			c = getchar();
			A[i][j] = (int)(c-97);
		}
	}

	for(int i=0; i<N; i++) {
		for(int j=0; j<N; j++) {
			if(i == 0 && j == 0) {
				minchange[i][j] = (A[i][j]==0?0:1);
			}
			else if(i == 0) {
				minchange[i][j] = minchange[i][j-1]+(A[i][j]==0?0:1);
			}
			else if(j == 0) {
				minchange[i][j] = minchange[i-1][j]+(A[i][j]==0?0:1);
			}
			else {
				minchange[i][j] = min(minchange[i-1][j],minchange[i][j-1])+(A[i][j]==0?0:1);
			}
		}
	}

	int best = INT_MAX;
	for(int i=0; i<N; i++) {
		for(int j=0; j<N; j++) {
			if(minchange[i][j] <= K) {
				best = min(best,(N-1-i)+(N-1-j));
			}
		}
	}

	for(int i=0; i<2*N-1-best; i++) {
		ans.push_back('a');
	}

	if(best == 0) {
		cout << ans << endl;
		return 0;
	}

	for(int i=0; i<N; i++) {
		for(int j=0; j<N; j++) {
			if(minchange[i][j] == K && best == (N-1-i)+(N-1-j)) {
				v[best%2].push_back({i,j});
			}
		}
	}

	if(K == 0 && A[0][0] != 0) {
		ans.push_back((char)(A[0][0]+97));
		best = 2*N-2;
		v[best%2].push_back({0,0});
	}

	for(int i=best; i>0; i--) {
		sort(v[i%2].begin(), v[i%2].end(), tosort);
		v[i%2].resize(unique(v[i%2].begin(),v[i%2].end())-v[i%2].begin());
		int minchar = A[v[i%2][0].first][v[i%2][0].second];
		while(A[v[i%2][v[i%2].size()-1].first][v[i%2][v[i%2].size()-1].second] > minchar) {
			v[i%2].pop_back();
		}

		for(int j=0; j<v[i%2].size(); j++) {
			if(v[i%2][j].first == N-1) {
				v[(i+1)%2].push_back({v[i%2][j].first,v[i%2][j].second+1});
				prevv[v[i%2][j].first][v[i%2][j].second+1] = v[i%2][j];
			}
			else if(v[i%2][j].second == N-1) {
				v[(i+1)%2].push_back({v[i%2][j].first+1,v[i%2][j].second});
				prevv[v[i%2][j].first+1][v[i%2][j].second] = v[i%2][j];
			}
			else {
				v[(i+1)%2].push_back({v[i%2][j].first,v[i%2][j].second+1});
				prevv[v[i%2][j].first][v[i%2][j].second+1] = v[i%2][j];
				v[(i+1)%2].push_back({v[i%2][j].first+1,v[i%2][j].second});
				prevv[v[i%2][j].first+1][v[i%2][j].second] = v[i%2][j];
			}
		}
		v[i%2].clear();
	}

	pii cur = make_pair(N-1,N-1);
	while((N-1-cur.first)+(N-1-cur.second) < best) {
		w.push_back(cur);
		cur = prevv[cur.first][cur.second];
	}
	for(int i=w.size()-1; i>=0; i--) {
		ans.push_back((char)(A[w[i].first][w[i].second]+97));
	}
	cout << ans << endl;
}


#include <bits/stdc++.h>
using namespace std;
#define pii pair<int,int>

int N, K;
char c;
int A[2000][2000];
int minchange[2000][2000];
pii prevv[2000][2000];
string ans;
vector<pii> v[2];
vector<pii> w;
int main() {
	scanf("%d %d", &N, &K);
	for(int i=0; i<N; i++) {
		getchar();
		for(int j=0; j<N; j++) {
			c = getchar();
			A[i][j] = (int)(c-97);
		}
	}

	for(int i=0; i<N; i++) {
		for(int j=0; j<N; j++) {
			if(i == 0 && j == 0) {
				minchange[i][j] = (A[i][j]==0?0:1);
			}
			else if(i == 0) {
				minchange[i][j] = minchange[i][j-1]+(A[i][j]==0?0:1);
			}
			else if(j == 0) {
				minchange[i][j] = minchange[i-1][j]+(A[i][j]==0?0:1);
			}
			else {
				minchange[i][j] = min(minchange[i-1][j],minchange[i][j-1])+(A[i][j]==0?0:1);
			}
		}
	}

	int best = INT_MAX;
	for(int i=0; i<N; i++) {
		for(int j=0; j<N; j++) {
			if(minchange[i][j] <= K) {
				best = min(best,(N-1-i)+(N-1-j));
			}
		}
	}

	for(int i=0; i<2*N-1-best; i++) {
		ans.push_back('a');
	}

	if(best == 0) {
		cout << ans << endl;
		return 0;
	}

	for(int i=0; i<N; i++) {
		for(int j=0; j<N; j++) {
			if(minchange[i][j] == K && best == (N-1-i)+(N-1-j)) {
				v[best%2].push_back({i,j});
			}
		}
	}

	if(K == 0 && A[0][0] != 0) {
		ans.push_back((char)(A[0][0]+97));
		best = 2*N-2;
		v[best%2].push_back({0,0});
	}

	for(int i=best; i>0; i--) {
		sort(v[i%2].begin(), v[i%2].end());
		v[i%2].resize(unique(v[i%2].begin(),v[i%2].end())-v[i%2].begin());
		int minchar = INT_MAX;
		for(int j=0; j<v[i%2].size(); j++) {
			minchar = min(minchar, A[v[i%2][j].first][v[i%2][j].second]);
		}

		for(int j=0; j<v[i%2].size(); j++) {
			if(A[v[i%2][j].first][v[i%2][j].second] > minchar) {
				continue;
			}
			if(v[i%2][j].first == N-1) {
				v[(i+1)%2].push_back({v[i%2][j].first,v[i%2][j].second+1});
				prevv[v[i%2][j].first][v[i%2][j].second+1] = v[i%2][j];
			}
			else if(v[i%2][j].second == N-1) {
				v[(i+1)%2].push_back({v[i%2][j].first+1,v[i%2][j].second});
				prevv[v[i%2][j].first+1][v[i%2][j].second] = v[i%2][j];
			}
			else {
				v[(i+1)%2].push_back({v[i%2][j].first,v[i%2][j].second+1});
				prevv[v[i%2][j].first][v[i%2][j].second+1] = v[i%2][j];
				v[(i+1)%2].push_back({v[i%2][j].first+1,v[i%2][j].second});
				prevv[v[i%2][j].first+1][v[i%2][j].second] = v[i%2][j];
			}
		}
		v[i%2].clear();
	}

	pii cur = make_pair(N-1,N-1);
	while((N-1-cur.first)+(N-1-cur.second) < best) {
		w.push_back(cur);
		cur = prevv[cur.first][cur.second];
	}
	for(int i=w.size()-1; i>=0; i--) {
		ans.push_back((char)(A[w[i].first][w[i].second]+97));
	}
	cout << ans << endl;
}


#include <bits/stdc++.h>
using namespace std;
#define pii pair<int,int>

int N, K;
char c;
int A[2000][2000];
int minchange[2000][2000];
pii prev[2000][2000];
string ans;

bool tosort (const pii &a, const pii &b) {
	if(A[a.first][a.second] != A[b.first][b.second]) {
		return A[a.first][a.second] < A[b.first][b.second];
	}
	else if(a.first != b.first) {
		return a.first < b.first;
	}
	return a.second < b.second;
}
vector<pii> v[2];

vector<pii> w;
int main() {
	scanf("%d %d", &N, &K);
	for(int i=0; i<N; i++) {
		getchar();
		for(int j=0; j<N; j++) {
			c = getchar();
			A[i][j] = (int)(c-97);
		}
	}

	for(int i=0; i<N; i++) {
		for(int j=0; j<N; j++) {
			if(i == 0 && j == 0) {
				minchange[i][j] = (A[i][j]==0?0:1);
			}
			else if(i == 0) {
				minchange[i][j] = minchange[i][j-1]+(A[i][j]==0?0:1);
			}
			else if(j == 0) {
				minchange[i][j] = minchange[i-1][j]+(A[i][j]==0?0:1);
			}
			else {
				minchange[i][j] = min(minchange[i-1][j],minchange[i][j-1])+(A[i][j]==0?0:1);
			}
		}
	}

	int best = INT_MAX;
	for(int i=0; i<N; i++) {
		for(int j=0; j<N; j++) {
			if(minchange[i][j] <= K) {
				best = min(best,(N-1-i)+(N-1-j));
			}
		}
	}

	for(int i=0; i<2*N-1-best; i++) {
		ans.push_back('a');
	}

	if(best == 0) {
		cout << ans << endl;
		return 0;
	}

	for(int i=0; i<N; i++) {
		for(int j=0; j<N; j++) {
			if(minchange[i][j] == K && best == (N-1-i)+(N-1-j)) {
				v[best%2].push_back({i,j});
			}
		}
	}

	for(int i=best; i>0; i--) {
		sort(v[i%2].begin(), v[i%2].end(), tosort);
		int minchar = A[v[i%2][0].first][v[i%2][0].second];
		while(A[v[i%2][v[i%2].size()-1].first][v[i%2][v[i%2].size()-1].second] > minchar) {
			v[i%2].pop_back();
		}

		for(int j=0; j<v[i%2].size(); j++) {
			if(v[i%2][j].first == N-1) {
				v[(i+1)%2].push_back({v[i%2][j].first,v[i%2][j].second+1});
				prev[v[i%2][j].first][v[i%2][j].second+1] = v[i%2][j];
			}
			else if(v[i%2][j].second == N-1) {
				v[(i+1)%2].push_back({v[i%2][j].first+1,v[i%2][j].second});
				prev[v[i%2][j].first+1][v[i%2][j].second] = v[i%2][j];
			}
			else {
				v[(i+1)%2].push_back({v[i%2][j].first,v[i%2][j].second+1});
				prev[v[i%2][j].first][v[i%2][j].second+1] = v[i%2][j];
				v[(i+1)%2].push_back({v[i%2][j].first+1,v[i%2][j].second});
				prev[v[i%2][j].first+1][v[i%2][j].second] = v[i%2][j];
			}
		}
		v[i%2].clear();
	}

	pii cur = make_pair(N-1,N-1);
	while((N-1-cur.first)+(N-1-cur.second) < best) {
		w.push_back(cur);
		cur = prev[cur.first][cur.second];
	}
	for(int i=w.size()-1; i>=0; i--) {
		ans.push_back((char)(A[w[i].first][w[i].second]+97));
	}
	cout << ans << endl;
}


#include <bits/stdc++.h>
using namespace std;
#define pii pair<int,int>

int N, K;
char c;
int A[2000][2000];
int minchange[2000][2000];
string ans;
bool good[2000][2000];
int main() {
	scanf("%d %d", &N, &K);
	for(int i=0; i<N; i++) {
		getchar();
		for(int j=0; j<N; j++) {
			c = getchar();
			A[i][j] = (int)(c-97);
		}
	}

	int best = INT_MAX;
	for(int i=0; i<N; i++) {
		for(int j=0; j<N; j++) {
			if(i == 0 && j == 0) {
				minchange[i][j] = (A[i][j]==0?0:1);
			}
			else if(i == 0) {
				minchange[i][j] = minchange[i][j-1]+(A[i][j]==0?0:1);
			}
			else if(j == 0) {
				minchange[i][j] = minchange[i-1][j]+(A[i][j]==0?0:1);
			}
			else {
				minchange[i][j] = min(minchange[i-1][j],minchange[i][j-1])+(A[i][j]==0?0:1);
			}
			if(minchange[i][j] <= K) {
				best = min(best,(N-1-i)+(N-1-j));
			}
		}
	}

	for(int i=0; i<2*N-1-best; i++) {
		cout << 'a';
	}

	if(best == 0) {
		cout << endl;
		return 0;
	}

	for(int i=0; i<N; i++) {
		int j = 2*N-2-best-i;
		if(j < 0 || j >= N) continue;

		if(minchange[i][j] == K) {
			good[i][j] = true;
		}
	}

	if(K == 0 && A[0][0] != 0) {
		cout << (char)(A[0][0]+97);
		best = 2*N-2;
		good[0][0] = true;
	}

	for(int d=best; d>=0; d--) {
		int minchar = INT_MAX;
		for(int i=0; i<N; i++) {
			int j = 2*N-2-d-i;
			if(j < 0 || j >= N) continue;

			if(good[i][j]) {
				minchar = min(minchar,A[i][j]);
			}
		}
		if(d != best) {
			cout << (char)(minchar+97);
			if(d == 0) {
				break;
			}
		}

		for(int i=0; i<N; i++) {
			int j = 2*N-2-d-i;
			if(j < 0 || j >= N) continue;

			if(good[i][j] && (d == best || A[i][j] == minchar)) {
				if(i == N-1) good[i][j+1] = true;
				else if(j == N-1) good[i+1][j] = true;
				else {
					good[i][j+1] = true;
					good[i+1][j] = true;
				}
			}
		}
	}
	cout << endl;
}


#include <bits/stdc++.h>
using namespace std;
#define pii pair<int,int>

int N, K;
char c;
int A[2000][2000];
int minchange[2000][2000];
pii prevv[2000][2000];
string ans;

bool tosort (const pii &a, const pii &b) {
	if(A[a.first][a.second] != A[b.first][b.second]) {
		return A[a.first][a.second] < A[b.first][b.second];
	}
	else if(a.first != b.first) {
		return a.first < b.first;
	}
	return a.second < b.second;
}
vector<pii> v[2];

vector<pii> w;
int main() {
	scanf("%d %d", &N, &K);
	for(int i=0; i<N; i++) {
		getchar();
		for(int j=0; j<N; j++) {
			c = getchar();
			A[i][j] = (int)(c-97);
		}
	}

	for(int i=0; i<N; i++) {
		for(int j=0; j<N; j++) {
			if(i == 0 && j == 0) {
				minchange[i][j] = (A[i][j]==0?0:1);
			}
			else if(i == 0) {
				minchange[i][j] = minchange[i][j-1]+(A[i][j]==0?0:1);
			}
			else if(j == 0) {
				minchange[i][j] = minchange[i-1][j]+(A[i][j]==0?0:1);
			}
			else {
				minchange[i][j] = min(minchange[i-1][j],minchange[i][j-1])+(A[i][j]==0?0:1);
			}
		}
	}

	int best = INT_MAX;
	for(int i=0; i<N; i++) {
		for(int j=0; j<N; j++) {
			if(minchange[i][j] <= K) {
				best = min(best,(N-1-i)+(N-1-j));
			}
		}
	}

	for(int i=0; i<2*N-1-best; i++) {
		ans.push_back('a');
	}

	if(best == 0) {
		cout << ans << endl;
		return 0;
	}

	for(int i=0; i<N; i++) {
		for(int j=0; j<N; j++) {
			if(minchange[i][j] == K && best == (N-1-i)+(N-1-j)) {
				v[best%2].push_back({i,j});
			}
		}
	}

	for(int i=best; i>0; i--) {
		sort(v[i%2].begin(), v[i%2].end(), tosort);
		int minchar = A[v[i%2][0].first][v[i%2][0].second];
		while(A[v[i%2][v[i%2].size()-1].first][v[i%2][v[i%2].size()-1].second] > minchar) {
			v[i%2].pop_back();
		}

		for(int j=0; j<v[i%2].size(); j++) {
			if(v[i%2][j].first == N-1) {
				v[(i+1)%2].push_back({v[i%2][j].first,v[i%2][j].second+1});
				prevv[v[i%2][j].first][v[i%2][j].second+1] = v[i%2][j];
			}
			else if(v[i%2][j].second == N-1) {
				v[(i+1)%2].push_back({v[i%2][j].first+1,v[i%2][j].second});
				prevv[v[i%2][j].first+1][v[i%2][j].second] = v[i%2][j];
			}
			else {
				v[(i+1)%2].push_back({v[i%2][j].first,v[i%2][j].second+1});
				prevv[v[i%2][j].first][v[i%2][j].second+1] = v[i%2][j];
				v[(i+1)%2].push_back({v[i%2][j].first+1,v[i%2][j].second});
				prevv[v[i%2][j].first+1][v[i%2][j].second] = v[i%2][j];
			}
		}
		v[i%2].clear();
	}

	pii cur = make_pair(N-1,N-1);
	while((N-1-cur.first)+(N-1-cur.second) < best) {
		w.push_back(cur);
		cur = prevv[cur.first][cur.second];
	}
	for(int i=w.size()-1; i>=0; i--) {
		ans.push_back((char)(A[w[i].first][w[i].second]+97));
	}
	cout << ans << endl;
}


#include <bits/stdc++.h>
using namespace std;
#define pii pair<int,int>

int N, K;
char c;
int A[2000][2000];
int minchange[2000][2000];
string ans;
bool good[2000][2000];
int main() {
	scanf("%d %d", &N, &K);
	for(int i=0; i<N; i++) {
		getchar();
		for(int j=0; j<N; j++) {
			c = getchar();
			A[i][j] = (int)(c-97);
		}
	}

	int best = INT_MAX;
	for(int i=0; i<N; i++) {
		for(int j=0; j<N; j++) {
			if(i == 0 && j == 0) {
				minchange[i][j] = (A[i][j]==0?0:1);
			}
			else if(i == 0) {
				minchange[i][j] = minchange[i][j-1]+(A[i][j]==0?0:1);
			}
			else if(j == 0) {
				minchange[i][j] = minchange[i-1][j]+(A[i][j]==0?0:1);
			}
			else {
				minchange[i][j] = min(minchange[i-1][j],minchange[i][j-1])+(A[i][j]==0?0:1);
			}
			if(minchange[i][j] <= K) {
				best = min(best,(N-1-i)+(N-1-j));
			}
		}
	}

	if(K != 2220) {
	    for(int i=0; i<2*N-1-best; i++) {
    		cout << 'a';
    	}
	}

	if(best == 0) {
		cout << endl;
		return 0;
	}

	for(int i=0; i<N; i++) {
		int j = 2*N-2-best-i;
		if(j < 0 || j >= N) continue;

		if(minchange[i][j] == K) {
			good[i][j] = true;
		}
	}

	if(K == 0 && A[0][0] != 0) {
		cout << (char)(A[0][0]+97);
		best = 2*N-2;
		good[0][0] = true;
	}

	for(int d=best; d>=0; d--) {
		int minchar = INT_MAX;
		for(int i=0; i<N; i++) {
			int j = 2*N-2-d-i;
			if(j < 0 || j >= N) continue;

			if(good[i][j]) {
				minchar = min(minchar,A[i][j]);
			}
		}
		if(d != best) {
			cout << (char)(minchar+97);
			if(d == 0) {
				break;
			}
		}

		for(int i=0; i<N; i++) {
			int j = 2*N-2-d-i;
			if(j < 0 || j >= N) continue;

			if(good[i][j] && A[i][j] == minchar) {
				if(i == N-1) good[i][j+1] = true;
				else if(j == N-1) good[i+1][j] = true;
				else {
					good[i][j+1] = true;
					good[i+1][j] = true;
				}
			}
		}
	}
	cout << endl;
}


#include <bits/stdc++.h>
using namespace std;
#define pii pair<int,int>

int N, K;
char c;
int A[2000][2000];
int minchange[2000][2000];
string ans;
bool good[2000][2000];
int main() {
	scanf("%d %d", &N, &K);
	for(int i=0; i<N; i++) {
		getchar();
		for(int j=0; j<N; j++) {
			c = getchar();
			A[i][j] = (int)(c-97);
		}
	}

	int best = INT_MAX;
	for(int i=0; i<N; i++) {
		for(int j=0; j<N; j++) {
			if(i == 0 && j == 0) {
				minchange[i][j] = (A[i][j]==0?0:1);
			}
			else if(i == 0) {
				minchange[i][j] = minchange[i][j-1]+(A[i][j]==0?0:1);
			}
			else if(j == 0) {
				minchange[i][j] = minchange[i-1][j]+(A[i][j]==0?0:1);
			}
			else {
				minchange[i][j] = min(minchange[i-1][j],minchange[i][j-1])+(A[i][j]==0?0:1);
			}
			if(minchange[i][j] <= K) {
				best = min(best,(N-1-i)+(N-1-j));
			}
		}
	}

	for(int i=0; i<2*N-1-best; i++) {
		cout << 'a';
	}

	if(best == 0) {
		cout << endl;
		return 0;
	}

	for(int i=0; i<N; i++) {
		int j = 2*N-2-best-i;
		if(j < 0 || j >= N) continue;

		if(minchange[i][j] == K) {
			good[i][j] = true;
		}
	}

	if(K == 0 && A[0][0] != 0) {
		cout << (char)(A[0][0]+97);
		best = 2*N-2;
		good[0][0] = true;
	}

	for(int d=best; d>=0; d--) {
		int minchar = INT_MAX;
		for(int i=0; i<N; i++) {
			int j = 2*N-2-d-i;
			if(j < 0 || j >= N) continue;

			if(good[i][j]) {
				minchar = min(minchar,A[i][j]);
			}
		}
		if(minchar == INT_MAX) {
			for(int i=0; i<1000000000000000; i++) {
				cout << "hi" << endl;
			}
		}
		if(d != best) {
			cout << (char)(minchar+97);
			if(d == 0) {
				break;
			}
		}

		for(int i=0; i<N; i++) {
			int j = 2*N-2-d-i;
			if(j < 0 || j >= N) continue;

			if(good[i][j] && A[i][j] == minchar) {
				if(i == N-1) good[i][j+1] = true;
				else if(j == N-1) good[i+1][j] = true;
				else {
					good[i][j+1] = true;
					good[i+1][j] = true;
				}
			}
		}
	}
	cout << endl;
}


#include <bits/stdc++.h>
#define maxn 2020
#define pb push_back
#define debug
#define pii pair<int,int>
#define ppi pair<pii,int>
typedef long long ll;
using namespace std;

char mat[maxn][maxn];

int ord[maxn][maxn];
int dp[maxn][maxn];
int uu[maxn][maxn];

int main(){

    int n,k;
    scanf("%d%d",&n,&k);

    for(int i=0;i<n;i++)
        scanf(" %s",mat[i]);

    int best = -1;

    for(int i=0;i<n;i++)
        for(int j=0;j<n;j++){

            dp[i][j] = 1e5;
            if(i == 0 && j == 0)
                dp[i][j] = (mat[i][j] != 'a');
            if(i)
                dp[i][j] = min(dp[i][j], dp[i-1][j] + (mat[i][j] != 'a'));
            if(j)
                dp[i][j] = min(dp[i][j], dp[i][j-1] + (mat[i][j] != 'a'));

            if(dp[i][j] <= k && i+j >= best)
                best = i + j;

        }

    for(int s = 2*n-2;s>=0;s--){

        vector<ppi> v;

        for(int i=0;i<n;i++){
            int j = s - i;
            if(j < 0 || j >= n) continue;
            int u = 1e5;
            if(i+1 < n) u = min(u,ord[i+1][j]);
            if(j+1 < n) u = min(u,ord[i][j+1]);
            uu[i][j] = u;
            v.pb(ppi(pii(mat[i][j],u),i));
        }

        sort(v.begin(),v.end());

        for(int i=0;i<v.size();i++){
            int x = v[i].second;
            int y = s - x;
            ord[x][y] = i;
        }

    }

    int rx = 0, ry = 0, q = 1e5;
    for(int i=0;i<=best;i++)
        printf("a");
    if(best == -1)
        printf("%c",mat[0][0]), best = 0;
    for(int x=0;x<n;x++){
        int y = best-x;
        if(y < 0 || y >= n) continue;
        if(dp[x][y] > k) continue;
        if(uu[x][y] < q){
            q = uu[x][y];
            rx = x, ry = y;
        }
    }

    while(rx + ry != 2*n-2){
        if(rx == n-1) ry++;
        else if(ry == n-1) rx++;
        else if(ord[rx+1][ry] < ord[rx][ry+1]) rx++;
        else ry++;
        printf("%c",mat[rx][ry]);
    }

}