Analysis: Watering the Fields by Fatih Gelgi


The problem description easily reveals the Minimum Spanning Tree solution. Fields are vertices and squared Euclidean distance is the weight of the edge of a field pair. We just need to disregard the edges that are less than C. Then running MST will solve the problem. If there is a field that cannot be reached (all distances to that field is less than C), the output will be -1.

Representing the graph with adjacency matrix requires O(N^2) memory. We can use it since N is small. Note that representing the graph with an adjacency list is not necessary; in fact it complicates the problem. The running time of Prim's MST algorithm on adjacency matrix is also O(N^2) which is sufficient for the problem. The sample code is as follows:

/* MST with adjacency matrix: O(n^2) */
#include <fstream>

#define MAX 2000

using namespace std;

int n,c,x[MAX],y[MAX],mat[MAX][MAX];

// MST with Prim
int mst()
{
	int from[MAX];
	bool mark[MAX];
	fill(from,from+n,-1);
	fill(mark,mark+n,false);

	int x=0,l=0;			// start from vertex 0
					// initial length of MST is 0
	for (int i=0; i<n-1; i++)
	{
		mark[x]=true;

		// expand the vertex and update edges in the queue
		for (int j=0; j<n; j++)
			if (!mark[j])
				if (mat[x][j])	// if there is (x,j) edge
					if (from[j]==-1 || mat[from[j]][j]>mat[x][j])
						from[j]=x;

		// choose the unused edge with minimum length in the queue
		x=-1;
		for (int j=0; j<n; j++)
			if (!mark[j] && from[j]!=-1)
				if (x==-1 || mat[from[x]][x]>mat[from[j]][j])
					x=j;

		// if graph is not connected
		if (x==-1) return -1;

		// update total cost of mst
		l+=mat[from[x]][x];
	}

	return l;
}

int main()
{
	ifstream fin("irrigation.in");
	int m;
	fin >> n >> c;
	for (int i=0; i<n; i++)
		fin >> x[i] >> y[i];
	fin.close();

	// construct the MST graph
	for (int i=0; i<n; i++)
		for (int j=0; j<n; j++)
		{
			mat[i][j]=(x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]);
			// remove the edge from graph if cost is less than c
			if (mat[i][j]<c) mat[i][j]=0;
		}

	ofstream fout("irrigation.out");
	fout << mst() << endl;	// write total length of MST
	fout.close();
}

Although it is not necessary, we can optimize the memory usage and reduce it to O(N). Since the graph is in 2D plane, it is a fully connected graph i.e. any vertex pair has an edge between them. Hence we don't need to keep the matrix. Here's a sample code:

/* MST with Prim: O(n^2) */
#include <fstream>
#include <algorithm>

#define MAX 2000

using namespace std;

int n,c,x[MAX],y[MAX],dist[MAX];

int main()
{
	ifstream fin("irrigation.in");
	fin >> n >> c;
	for (int i=0; i<n; i++) fin >> x[i] >> y[i];
	fin.close();

	int k=0,l=0;			// start from vertex 0
					// initial length of MST is 0
	fill(dist,dist+n,1000000000);

	for (int i=0; i<n-1; i++)
	{
		dist[k]=-1;		// mark used vertices

		// explore vertices and update edges in the queue
		for (int j=0; j<n; j++)
		{
			int d=(x[k]-x[j])*(x[k]-x[j])+(y[k]-y[j])*(y[k]-y[j]);
			// if (x,j) edge is long enough
			if (d>=c && d<dist[j]) dist[j]=d;
		}

		// choose the unused edge with minimum length in the queue
		k=-1;
		for (int j=0; j<n; j++)
			if (dist[j]!=-1 && dist[j]!=1000000000)
				if (k==-1 || dist[k]>dist[j]) k=j;

		if (k==-1) break;	// if graph is not connected
		l+=dist[k];		// update total cost of mst
	}
	if (k==-1) l=-1;

	ofstream fout("irrigation.out");
	fout << l << endl;
	fout.close();
}