//package vk2015.r1;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.Comparator;
import java.util.InputMismatchException;

public class D {
	InputStream is;
	PrintWriter out;
	String INPUT = "";

	void solve()
	{
		int n = ni(), m = ni(), t = ni();
		int[] a = new int[n];
		for(int i = 0;i < n;i++){
			a[i] = ni()*3600+ni()*60+ni();
		}
		if(n < m){
			out.println("No solution");
			return;
		}

		int online = 0;
		int gen = 0;

		int[][] rs = new int[2*n][];
		int[] stands = new int[n+3];
		int[] ids = new int[n];
		Arrays.fill(ids, -1);
		int last = -1;
		for(int i = 0;i < n;i++){
			rs[i] = new int[]{a[i], 1, i};
			rs[i+n] = new int[]{a[i]+t, -1, i};
		}
		Arrays.sort(rs, new Comparator<int[]>() {
			public int compare(int[] a, int[] b) {
				if(a[0] != b[0])return a[0] - b[0];
				return a[1] - b[1];
			}
		});
		for(int[] r : rs){
			if(r[1] == 1){
				if(online == m){
					ids[r[2]] = last;
					stands[last]++;
				}else{
					ids[r[2]] = last = ++gen;
					stands[last]++;
					online++;
				}
			}else{
				if(--stands[ids[r[2]]] == 0)online--;
			}
		}
		out.println(gen);
		for(int i = 0;i < n;i++){
			out.println(ids[i]);
		}
	}

	void run() throws Exception
	{
		is = oj ? System.in : new ByteArrayInputStream(INPUT.getBytes());
		out = new PrintWriter(System.out);

		long s = System.currentTimeMillis();
		solve();
		out.flush();
		tr(System.currentTimeMillis()-s+"ms");
	}

	public static void main(String[] args) throws Exception { new D().run(); }

	private byte[] inbuf = new byte[1024];
	private int lenbuf = 0, ptrbuf = 0;

	private int readByte()
	{
		if(lenbuf == -1)throw new InputMismatchException();
		if(ptrbuf >= lenbuf){
			ptrbuf = 0;
			try { lenbuf = is.read(inbuf); } catch (IOException e) { throw new InputMismatchException(); }
			if(lenbuf <= 0)return -1;
		}
		return inbuf[ptrbuf++];
	}

	private boolean isSpaceChar(int c) { return !(c >= 33 && c <= 126); }
	private int skip() { int b; while((b = readByte()) != -1 && isSpaceChar(b)); return b; }

	private double nd() { return Double.parseDouble(ns()); }
	private char nc() { return (char)skip(); }

	private String ns()
	{
		int b = skip();
		StringBuilder sb = new StringBuilder();
		while(!(isSpaceChar(b))){ // when nextLine, (isSpaceChar(b) && b != ' ')
			sb.appendCodePoint(b);
			b = readByte();
		}
		return sb.toString();
	}

	private char[] ns(int n)
	{
		char[] buf = new char[n];
		int b = skip(), p = 0;
		while(p < n && !(isSpaceChar(b))){
			buf[p++] = (char)b;
			b = readByte();
		}
		return n == p ? buf : Arrays.copyOf(buf, p);
	}

	private char[][] nm(int n, int m)
	{
		char[][] map = new char[n][];
		for(int i = 0;i < n;i++)map[i] = ns(m);
		return map;
	}

	private int[] na(int n)
	{
		int[] a = new int[n];
		for(int i = 0;i < n;i++)a[i] = ni();
		return a;
	}

	private int ni()
	{
		int num = 0, b;
		boolean minus = false;
		while((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-'));
		if(b == '-'){
			minus = true;
			b = readByte();
		}

		while(true){
			if(b >= '0' && b <= '9'){
				num = num * 10 + (b - '0');
			}else{
				return minus ? -num : num;
			}
			b = readByte();
		}
	}

	private long nl()
	{
		long num = 0;
		int b;
		boolean minus = false;
		while((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-'));
		if(b == '-'){
			minus = true;
			b = readByte();
		}

		while(true){
			if(b >= '0' && b <= '9'){
				num = num * 10 + (b - '0');
			}else{
				return minus ? -num : num;
			}
			b = readByte();
		}
	}

	private boolean oj = System.getProperty("ONLINE_JUDGE") != null;
	private void tr(Object... o) { if(!oj)System.out.println(Arrays.deepToString(o)); }
}


import java.util.*;

public class D {
  static int read_time(Scanner in) {
    String[] arr = in.next().split(":");
    return Integer.parseInt(arr[0])*3600 +
           Integer.parseInt(arr[1])*60 +
           Integer.parseInt(arr[2]);
  }
  public static void main(String[] args) {
    Scanner in = new Scanner(System.in);
    PriorityQueue<int[]> PQ = new PriorityQueue<int[]>(10, new Comparator<int[]>() {
      public int compare(int[] a, int[] b) {
        return a[0]-b[0];
      }
    });
    Map<Integer, Integer> LIVES = new HashMap<Integer, Integer>();

    int n = in.nextInt();
    int M = in.nextInt();
    int T = in.nextInt();

    int next_id = 1;
    int[] A = new int[n];
    boolean reached_max  = false;

    for(int i=0; i<n; i++) {
      int time = read_time(in);
      while(!PQ.isEmpty()) {
        int[] t_id = PQ.poll();
        if(time <= t_id[0]) {
          PQ.offer(t_id);
          break;
        } else {
          int id = t_id[1];
          int lives = LIVES.get(id);
          if(lives==1) {
            LIVES.remove(id);
          } else {
            LIVES.put(id, lives-1);
          }
        }
      }
      if(LIVES.size() == M) {
        int last_id = next_id-1;
        PQ.offer(new int[]{time+T-1, last_id});
        LIVES.put(last_id, LIVES.get(last_id)+1);
        A[i] = last_id;
      } else {
        PQ.offer(new int[]{time+T-1, next_id});
        LIVES.put(next_id, 1);
        A[i] = next_id;
        next_id++;
      }
      if(LIVES.size() == M) { reached_max=true; }
    }
    if(!reached_max) {
      System.out.println("No solution");
    } else {
      System.out.println(next_id-1);
      for(int i=0; i<n; i++) {
        System.out.println(A[i]);
      }
    }
  }
}


import java.util.*;

public class D {
  static int read_time(Scanner in) {
    String[] arr = in.next().split(":");
    return Integer.parseInt(arr[0])*3600 +
           Integer.parseInt(arr[1])*60 +
           Integer.parseInt(arr[2]);
  }
  public static void main(String[] args) {
    Scanner in = new Scanner(System.in);
    PriorityQueue<int[]> PQ = new PriorityQueue<int[]>(10, new Comparator<int[]>() {
      public int compare(int[] a, int[] b) {
        return a[0]-b[0];
      }
    });
    Map<Integer, Integer> ID_TO_T = new HashMap<Integer, Integer>();

    int n = in.nextInt();
    int M = in.nextInt();
    int T = in.nextInt();

    int next_id = 1;
    int[] A = new int[n];
    boolean reached_max  = false;

    for(int i=0; i<n; i++) {
      int time = read_time(in);
      while(!PQ.isEmpty()) {
        int[] t_id = PQ.poll();
        System.out.println(t_id[0]);
        if(time <= t_id[0]) {
          PQ.offer(t_id);
          break;
        } else {
          ID_TO_T.remove(t_id[1]);
        }
      }
      System.out.println(time+" "+PQ+" "+M);
      if(PQ.size() == M) {
        int last_id = next_id-1;
        int last_time = ID_TO_T.get(last_id);
        PQ.remove(new int[]{last_time, last_id});
        PQ.offer(new int[]{time+T-1, last_id});
        ID_TO_T.put(last_id, time+T-1);
        A[i] = last_id;
      } else {
        PQ.offer(new int[]{time+T-1, next_id});
        ID_TO_T.put(next_id, time+T-1);
        A[i] = next_id;
        next_id++;
      }
      if(PQ.size() == M) { reached_max=true; }
    }
    if(!reached_max) {
      System.out.println("No solution");
    } else {
      System.out.println(next_id-1);
      for(int i=0; i<n; i++) {
        System.out.println(A[i]);
      }
    }
  }
}


import java.util.*;

public class D {
  static int read_time(Scanner in) {
    String[] arr = in.next().split(":");
    return Integer.parseInt(arr[0])*3600 +
           Integer.parseInt(arr[1])*60 +
           Integer.parseInt(arr[2]);
  }
  public static void main(String[] args) {
    Scanner in = new Scanner(System.in);
    PriorityQueue<int[]> PQ = new PriorityQueue<int[]>(10, new Comparator<int[]>() {
      public int compare(int[] a, int[] b) {
        return a[0]-b[0];
      }
    });
    Map<Integer, Integer> ID_TO_T = new HashMap<Integer, Integer>();

    int n = in.nextInt();
    int M = in.nextInt();
    int T = in.nextInt();

    int next_id = 1;
    int[] A = new int[n];
    boolean reached_max  = false;

    for(int i=0; i<n; i++) {
      int time = read_time(in);
      while(!PQ.isEmpty()) {
        int[] t_id = PQ.poll();
        if(time <= t_id[0]) {
          PQ.offer(t_id);
          break;
        } else {
          ID_TO_T.remove(t_id[1]);
        }
      }
      if(PQ.size() == M) {
        int last_id = next_id-1;
        int last_time = ID_TO_T.get(last_id);
        PQ.remove(new int[]{last_time, last_id});
        PQ.offer(new int[]{time+T-1, last_id});
        ID_TO_T.put(last_id, time+T-1);
        A[i] = last_id;
      } else {
        PQ.offer(new int[]{time+T-1, next_id});
        ID_TO_T.put(next_id, time+T-1);
        A[i] = next_id;
        next_id++;
      }
      if(PQ.size() == M) { reached_max=true; }
    }
    if(!reached_max) {
      System.out.println("No solution");
    } else {
      System.out.println(next_id-1);
      for(int i=0; i<n; i++) {
        System.out.println(A[i]);
      }
    }
  }
}


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.TreeSet;

public class D {
	static InputStreamReader isr = new InputStreamReader(System.in);
	static BufferedReader br = new BufferedReader(isr);

	static int[] readIntArray() throws IOException {
		String[] v = br.readLine().split(" ");
		int[] ans = new int[v.length];

		for (int i = 0; i < ans.length; i++) {
			ans[i] = Integer.valueOf(v[i]);
		}

		return ans;
	}

	static int n, m, t;
	static int[] r;
	static TreeSet<Long> sessions;
	static HashMap<Integer, Integer> logoutByID;
	static HashMap<Integer, Integer> userByRequest;
	static int currentID = 1;
	static String noSolution = "No solution";

	public static void main(String[] args) throws IOException {
		logoutByID = new HashMap<Integer, Integer>();
		userByRequest = new HashMap<Integer, Integer>();
		sessions = new TreeSet<Long>();

		int[] l = readIntArray();
		n = l[0];
		m = l[1];
		t = l[2];
		if (n < m) {
			System.out.println(noSolution);
			return;
		}

		r = new int[n];
		for (int i = 0; i < n; i++) {
			r[i] = parse(br.readLine());
		}
		boolean reached = false;
		for (int i = 0; i < r.length; i++) {
			long k = getKey(r[i], 0);
			int alive = sessions.tailSet(k, true).size();
			sessions.headSet(k).clear();
			if (alive < m) {
				sessions.add(getKey(r[i] + t - 1, currentID));
				logoutByID.put(currentID, r[i] + t - 1);
				userByRequest.put(i, currentID);
				currentID++;
			} else {
				reached = true;
				int logout = logoutByID.get(currentID - 1);
				logoutByID.put(currentID - 1, r[i] + t - 1);
				sessions.remove(getKey(logout, currentID - 1));
				sessions.add(getKey(r[i]+t-1, currentID - 1));
				userByRequest.put(i, currentID - 1);
			}
		}

		if(!reached) {
			System.out.println(noSolution);
			return;
		}

		System.out.println(currentID - 1);
		StringBuilder sb = new StringBuilder();
		for (int i = 0; i < n; i++) {
			if (sb.length() > 0) {
				sb.append('\n');
			}
			sb.append(userByRequest.get(i));
		}
		System.out.println(sb.toString());
	}

	static Long getKey(int timestamp, int id) {
		long k = timestamp;
		k *= 100000;
		k += id;
//		return String.format("%05d", timestamp) + "-" + id;
		return k;
	}

	private static int parse(String line) {
		String[] v = line.split(":");
		int ans = 0;
		ans = Integer.valueOf(v[0]) * 3600 + Integer.valueOf(v[1]) * 60 + Integer.valueOf(v[2]);

		return ans;
	}
}


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.TreeSet;

public class D {
	static InputStreamReader isr = new InputStreamReader(System.in);
	static BufferedReader br = new BufferedReader(isr);

	static int[] readIntArray() throws IOException {
		String[] v = br.readLine().split(" ");
		int[] ans = new int[v.length];

		for (int i = 0; i < ans.length; i++) {
			ans[i] = Integer.valueOf(v[i]);
		}

		return ans;
	}

	static int n, m, t;
	static int[] r;
	static TreeSet<String> sessions;
	static HashMap<Integer, Integer> logoutByID;
	static HashMap<Integer, Integer> userByRequest;
	static int currentID = 1;
	static String noSolution = "No solution";

	public static void main(String[] args) throws IOException {
		logoutByID = new HashMap<Integer, Integer>();
		userByRequest = new HashMap<Integer, Integer>();
		sessions = new TreeSet<String>();

		int[] l = readIntArray();
		n = l[0];
		m = l[1];
		t = l[2];
		if (n < m) {
			System.out.println(noSolution);
			return;
		}

		r = new int[n];
		for (int i = 0; i < n; i++) {
			r[i] = parse(br.readLine());
		}
		for (int i = 0; i < r.length; i++) {
			String k = getKey(r[i], 0);
			int alive = sessions.tailSet(k, true).size();
			if (alive < m) {
				sessions.add(getKey(r[i] + t - 1, currentID));
				logoutByID.put(currentID, r[i] + t - 1);
				userByRequest.put(i, currentID);
				currentID++;
			} else {
				int logout = logoutByID.get(currentID - 1);
				logoutByID.put(currentID - 1, logout + t - 1);
				sessions.remove(getKey(logout, currentID - 1));
				sessions.add(getKey(logout+t-1, currentID - 1));
				userByRequest.put(i, currentID - 1);
			}
		}

		System.out.println(currentID - 1);
		StringBuilder sb = new StringBuilder();
		for (int i = 0; i < n; i++) {
			if (sb.length() > 0) {
				sb.append('\n');
			}
			sb.append(userByRequest.get(i));
		}
		System.out.println(sb.toString());
	}

	static String getKey(int timestamp, int id) {
		return String.format("%010d", timestamp) + "-" + id;
	}

	private static int parse(String line) {
		String[] v = line.split(":");
		int ans = 0;
		ans = Integer.valueOf(v[0]) * 3600 + Integer.valueOf(v[1]) * 60 + Integer.valueOf(v[2]);

		return ans;
	}
}


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;

public class D {
	static InputStreamReader isr = new InputStreamReader(System.in);
	static BufferedReader br = new BufferedReader(isr);

	static int[] readIntArray() throws IOException {
		String[] v = br.readLine().split(" ");
		int[] ans = new int[v.length];

		for (int i = 0; i < ans.length; i++) {
			ans[i] = Integer.valueOf(v[i]);
		}

		return ans;
	}

	static int n, m, t;
	static int[] r;
	static List<Long> sessions;
	static HashMap<Integer, Integer> userByRequest;
	static int currentID = 1;
	static String noSolution = "No solution";

	public static void main(String[] args) throws IOException {
		userByRequest = new HashMap<Integer, Integer>();
		sessions = new ArrayList<Long>();

		int[] l = readIntArray();
		n = l[0];
		m = l[1];
		t = l[2];
		if (n < m) {
			System.out.println(noSolution);
			return;
		}

		r = new int[n];
		for (int i = 0; i < n; i++) {
			r[i] = parse(br.readLine());
		}
		boolean reached = false;
		for (int i = 0; i < r.length; i++) {
			long k = getKey(r[i], 0) - 1;
			int alive = Collections.binarySearch(sessions, k, null);
			alive += 1;
			alive = -alive;
			alive = sessions.size() - alive;

			if (alive < m) {
				sessions.add(getKey(r[i] + t - 1, currentID));
				userByRequest.put(i, currentID);
				currentID++;
			} else {
				reached = true;
				sessions.remove(sessions.size() - 1);
				sessions.add(getKey(r[i] + t - 1, currentID - 1));
				userByRequest.put(i, currentID - 1);
			}
		}

		if (!reached) {
			System.out.println(noSolution);
			return;
		}

		System.out.println(currentID - 1);
		StringBuilder sb = new StringBuilder();
		for (int i = 0; i < n; i++) {
			if (sb.length() > 0) {
				sb.append('\n');
			}
			sb.append(userByRequest.get(i));
		}
		System.out.println(sb.toString());
	}

	static Long getKey(int timestamp, int id) {
		long k = timestamp;
		k *= 100000;
		k += id;
		// return String.format("%05d", timestamp) + "-" + id;
		return k;
	}

	private static int parse(String line) {
		String[] v = line.split(":");
		int ans = 0;
		ans = Integer.valueOf(v[0]) * 3600 + Integer.valueOf(v[1]) * 60
				+ Integer.valueOf(v[2]);

		return ans;
	}
}


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;

public class D {
	static InputStreamReader isr = new InputStreamReader(System.in);
	static BufferedReader br = new BufferedReader(isr);

	static int[] readIntArray() throws IOException {
		String[] v = br.readLine().split(" ");
		int[] ans = new int[v.length];

		for (int i = 0; i < ans.length; i++) {
			ans[i] = Integer.valueOf(v[i]);
		}

		return ans;
	}

	static int n, m, t;
	static int[] r;
	static List<Long> sessions;
	static HashMap<Integer, Integer> userByRequest;
	static int currentID = 1;
	static String noSolution = "No solution";

	public static void main(String[] args) throws IOException {
		userByRequest = new HashMap<Integer, Integer>();
		sessions = new ArrayList<Long>();

		int[] l = readIntArray();
		n = l[0];
		m = l[1];
		t = l[2];
		if (n < m) {
			System.out.println(noSolution);
			return;
		}

		r = new int[n];
		for (int i = 0; i < n; i++) {
			r[i] = parse(br.readLine());
		}
		boolean reached = false;
		for (int i = 0; i < r.length; i++) {
			long k = getKey(r[i], 0);
			int alive = Collections.binarySearch(sessions, k, null);
			alive += 1;
			alive = -alive;
			alive = sessions.size() - alive;

			if (alive < m) {
				sessions.add(getKey(r[i] + t - 1, currentID));
				userByRequest.put(i, currentID);
				currentID++;
				if (alive == m - 1) reached = true;
			} else {
				sessions.remove(sessions.size() - 1);
				sessions.add(getKey(r[i] + t - 1, currentID - 1));
				userByRequest.put(i, currentID - 1);
			}
		}

		if (!reached) {
			System.out.println(noSolution);
			return;
		}

		System.out.println(currentID - 1);
		StringBuilder sb = new StringBuilder();
		for (int i = 0; i < n; i++) {
			if (sb.length() > 0) {
				sb.append('\n');
			}
			sb.append(userByRequest.get(i));
		}
		System.out.println(sb.toString());
	}

	static Long getKey(int timestamp, int id) {
		long k = timestamp;
		k *= 100000;
		k += id;
		// return String.format("%05d", timestamp) + "-" + id;
		return k;
	}

	private static int parse(String line) {
		String[] v = line.split(":");
		int ans = 0;
		ans = Integer.valueOf(v[0]) * 3600 + Integer.valueOf(v[1]) * 60
				+ Integer.valueOf(v[2]);

		return ans;
	}
}


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.TreeSet;

public class D {
	static InputStreamReader isr = new InputStreamReader(System.in);
	static BufferedReader br = new BufferedReader(isr);

	static int[] readIntArray() throws IOException {
		String[] v = br.readLine().split(" ");
		int[] ans = new int[v.length];

		for (int i = 0; i < ans.length; i++) {
			ans[i] = Integer.valueOf(v[i]);
		}

		return ans;
	}

	static int n, m, t;
	static int[] r;
	static TreeSet<String> sessions;
	static HashMap<Integer, Integer> logoutByID;
	static HashMap<Integer, Integer> userByRequest;
	static int currentID = 1;
	static String noSolution = "No solution";

	public static void main(String[] args) throws IOException {
		logoutByID = new HashMap<Integer, Integer>();
		userByRequest = new HashMap<Integer, Integer>();
		sessions = new TreeSet<String>();

		int[] l = readIntArray();
		n = l[0];
		m = l[1];
		t = l[2];
		if (n < m) {
			System.out.println(noSolution);
			return;
		}

		r = new int[n];
		for (int i = 0; i < n; i++) {
			r[i] = parse(br.readLine());
		}
		boolean reached = false;
		for (int i = 0; i < r.length; i++) {
			String k = getKey(r[i], 0);
			int alive = sessions.tailSet(k, true).size();
			sessions.headSet(k).clear();
			if (alive < m) {
				sessions.add(getKey(r[i] + t - 1, currentID));
				logoutByID.put(currentID, r[i] + t - 1);
				userByRequest.put(i, currentID);
				currentID++;
			} else {
				reached = true;
				int logout = logoutByID.get(currentID - 1);
				logoutByID.put(currentID - 1, r[i] + t - 1);
				sessions.remove(getKey(logout, currentID - 1));
				sessions.add(getKey(r[i]+t-1, currentID - 1));
				userByRequest.put(i, currentID - 1);
			}
		}

		if(!reached) {
			System.out.println(noSolution);
			return;
		}

		System.out.println(currentID - 1);
		StringBuilder sb = new StringBuilder();
		for (int i = 0; i < n; i++) {
			if (sb.length() > 0) {
				sb.append('\n');
			}
			sb.append(userByRequest.get(i));
		}
		System.out.println(sb.toString());
	}

	static String getKey(int timestamp, int id) {
		return String.format("%05d", timestamp) + "-" + id;
	}

	private static int parse(String line) {
		String[] v = line.split(":");
		int ans = 0;
		ans = Integer.valueOf(v[0]) * 3600 + Integer.valueOf(v[1]) * 60 + Integer.valueOf(v[2]);

		return ans;
	}
}


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;

public class D {
	static InputStreamReader isr = new InputStreamReader(System.in);
	static BufferedReader br = new BufferedReader(isr);

	static int[] readIntArray() throws IOException {
		String[] v = br.readLine().split(" ");
		int[] ans = new int[v.length];

		for (int i = 0; i < ans.length; i++) {
			ans[i] = Integer.valueOf(v[i]);
		}

		return ans;
	}

	static int n, m, t;
	static int[] r;
	static List<Long> sessions;
	static HashMap<Integer, Integer> userByRequest;
	static int currentID = 1;
	static String noSolution = "No solution";

	public static void main(String[] args) throws IOException {
		userByRequest = new HashMap<Integer, Integer>();
		sessions = new ArrayList<Long>();

		int[] l = readIntArray();
		n = l[0];
		m = l[1];
		t = l[2];
		if (n < m) {
			System.out.println(noSolution);
			return;
		}

		r = new int[n];
		for (int i = 0; i < n; i++) {
			r[i] = parse(br.readLine());
		}
		boolean reached = false;
		for (int i = 0; i < r.length; i++) {
			long k = getKey(r[i], 0);
			int alive = Collections.binarySearch(sessions, k, null);
			alive += 1;
			alive = -alive;
			alive = sessions.size() - alive;

			if (alive < m) {
				sessions.add(getKey(r[i] + t - 1, currentID));
				userByRequest.put(i, currentID);
				currentID++;
			} else {
				reached = true;
				sessions.remove(sessions.size() - 1);
				sessions.add(getKey(r[i] + t - 1, currentID - 1));
				userByRequest.put(i, currentID - 1);
			}
		}

		if (!reached) {
			System.out.println(noSolution);
			return;
		}

		System.out.println(currentID - 1);
		StringBuilder sb = new StringBuilder();
		for (int i = 0; i < n; i++) {
			if (sb.length() > 0) {
				sb.append('\n');
			}
			sb.append(userByRequest.get(i));
		}
		System.out.println(sb.toString());
	}

	static Long getKey(int timestamp, int id) {
		long k = timestamp;
		k *= 100000;
		k += id;
		// return String.format("%05d", timestamp) + "-" + id;
		return k;
	}

	private static int parse(String line) {
		String[] v = line.split(":");
		int ans = 0;
		ans = Integer.valueOf(v[0]) * 3600 + Integer.valueOf(v[1]) * 60
				+ Integer.valueOf(v[2]);

		return ans;
	}
}


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;

public class D {
	static InputStreamReader isr = new InputStreamReader(System.in);
	static BufferedReader br = new BufferedReader(isr);

	static int[] readIntArray() throws IOException {
		String[] v = br.readLine().split(" ");
		int[] ans = new int[v.length];

		for (int i = 0; i < ans.length; i++) {
			ans[i] = Integer.valueOf(v[i]);
		}

		return ans;
	}

	static int n, m, t;
	static int[] r;
	static List<Long> sessions;
	static HashMap<Integer, Integer> userByRequest;
	static int currentID = 1;
	static String noSolution = "No solution";

	public static void main(String[] args) throws IOException {
		userByRequest = new HashMap<Integer, Integer>();
		sessions = new ArrayList<Long>();

		int[] l = readIntArray();
		n = l[0];
		m = l[1];
		t = l[2];
		if (n < m) {
			System.out.println(noSolution);
			return;
		}

		r = new int[n];
		for (int i = 0; i < n; i++) {
			r[i] = parse(br.readLine());
		}
		boolean reached = false;
		for (int i = 0; i < r.length; i++) {
			long k = getKey(r[i] - 1, 0);
			int alive = Collections.binarySearch(sessions, k, null);
			alive += 1;
			alive = -alive;
			alive = sessions.size() - alive;

			if (alive < m) {
				sessions.add(getKey(r[i] + t - 1, currentID));
				userByRequest.put(i, currentID);
				currentID++;
			} else {
				reached = true;
				sessions.remove(sessions.size() - 1);
				sessions.add(getKey(r[i] + t - 1, currentID - 1));
				userByRequest.put(i, currentID - 1);
			}
		}

		if (!reached) {
			System.out.println(noSolution);
			return;
		}

		System.out.println(currentID - 1);
		StringBuilder sb = new StringBuilder();
		for (int i = 0; i < n; i++) {
			if (sb.length() > 0) {
				sb.append('\n');
			}
			sb.append(userByRequest.get(i));
		}
		System.out.println(sb.toString());
	}

	static Long getKey(int timestamp, int id) {
		long k = timestamp;
		k *= 100000;
		k += id;
		// return String.format("%05d", timestamp) + "-" + id;
		return k;
	}

	private static int parse(String line) {
		String[] v = line.split(":");
		int ans = 0;
		ans = Integer.valueOf(v[0]) * 3600 + Integer.valueOf(v[1]) * 60
				+ Integer.valueOf(v[2]);

		return ans;
	}
}


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.TreeSet;

public class D {
	static InputStreamReader isr = new InputStreamReader(System.in);
	static BufferedReader br = new BufferedReader(isr);

	static int[] readIntArray() throws IOException {
		String[] v = br.readLine().split(" ");
		int[] ans = new int[v.length];

		for (int i = 0; i < ans.length; i++) {
			ans[i] = Integer.valueOf(v[i]);
		}

		return ans;
	}

	static int n, m, t;
	static int[] r;
	static TreeSet<String> sessions;
	static HashMap<Integer, Integer> logoutByID;
	static HashMap<Integer, Integer> userByRequest;
	static int currentID = 1;
	static String noSolution = "No solution";

	public static void main(String[] args) throws IOException {
		logoutByID = new HashMap<Integer, Integer>();
		userByRequest = new HashMap<Integer, Integer>();
		sessions = new TreeSet<String>();

		int[] l = readIntArray();
		n = l[0];
		m = l[1];
		t = l[2];
		if (n < m) {
			System.out.println(noSolution);
			return;
		}

		r = new int[n];
		for (int i = 0; i < n; i++) {
			r[i] = parse(br.readLine());
		}
		boolean reached = false;
		for (int i = 0; i < r.length; i++) {
			String k = getKey(r[i], 0);
			int alive = sessions.tailSet(k, true).size();
			if (alive < m) {
				sessions.add(getKey(r[i] + t - 1, currentID));
				logoutByID.put(currentID, r[i] + t - 1);
				userByRequest.put(i, currentID);
				currentID++;
			} else {
				reached = true;
				int logout = logoutByID.get(currentID - 1);
				logoutByID.put(currentID - 1, r[i] + t - 1);
				sessions.remove(getKey(logout, currentID - 1));
				sessions.add(getKey(r[i]+t-1, currentID - 1));
				userByRequest.put(i, currentID - 1);
			}
		}

		if(!reached) {
			System.out.println(noSolution);
			return;
		}

		System.out.println(currentID - 1);
		StringBuilder sb = new StringBuilder();
		for (int i = 0; i < n; i++) {
			if (sb.length() > 0) {
				sb.append('\n');
			}
			sb.append(userByRequest.get(i));
		}
		System.out.println(sb.toString());
	}

	static String getKey(int timestamp, int id) {
		return String.format("%05d", timestamp) + "-" + id;
	}

	private static int parse(String line) {
		String[] v = line.split(":");
		int ans = 0;
		ans = Integer.valueOf(v[0]) * 3600 + Integer.valueOf(v[1]) * 60 + Integer.valueOf(v[2]);

		return ans;
	}
}


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.TreeSet;

public class D {
	static InputStreamReader isr = new InputStreamReader(System.in);
	static BufferedReader br = new BufferedReader(isr);

	static int[] readIntArray() throws IOException {
		String[] v = br.readLine().split(" ");
		int[] ans = new int[v.length];

		for (int i = 0; i < ans.length; i++) {
			ans[i] = Integer.valueOf(v[i]);
		}

		return ans;
	}

	static int n, m, t;
	static int[] r;
	static TreeSet<String> sessions;
	static HashMap<Integer, Integer> logoutByID;
	static HashMap<Integer, Integer> userByRequest;
	static int currentID = 1;
	static String noSolution = "No solution";

	public static void main(String[] args) throws IOException {
		logoutByID = new HashMap<Integer, Integer>();
		userByRequest = new HashMap<Integer, Integer>();
		sessions = new TreeSet<String>();

		int[] l = readIntArray();
		n = l[0];
		m = l[1];
		t = l[2];
		if (n < m) {
			System.out.println(noSolution);
			return;
		}

		r = new int[n];
		for (int i = 0; i < n; i++) {
			r[i] = parse(br.readLine());
		}
		for (int i = 0; i < r.length; i++) {
			String k = getKey(r[i], 0);
			int alive = sessions.tailSet(k, true).size();
			if (alive < m) {
				sessions.add(getKey(r[i] + t - 1, currentID));
				logoutByID.put(currentID, r[i] + t - 1);
				userByRequest.put(i, currentID);
				currentID++;
			} else {
				int logout = logoutByID.get(currentID - 1);
				logoutByID.put(currentID - 1, r[i] + t - 1);
				sessions.remove(getKey(logout, currentID - 1));
				sessions.add(getKey(r[i]+t-1, currentID - 1));
				userByRequest.put(i, currentID - 1);
			}
		}

		System.out.println(currentID - 1);
		StringBuilder sb = new StringBuilder();
		for (int i = 0; i < n; i++) {
			if (sb.length() > 0) {
				sb.append('\n');
			}
			sb.append(userByRequest.get(i));
		}
		System.out.println(sb.toString());
	}

	static String getKey(int timestamp, int id) {
		return String.format("%010d", timestamp) + "-" + id;
	}

	private static int parse(String line) {
		String[] v = line.split(":");
		int ans = 0;
		ans = Integer.valueOf(v[0]) * 3600 + Integer.valueOf(v[1]) * 60 + Integer.valueOf(v[2]);

		return ans;
	}
}


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.TreeSet;

public class D {
	static InputStreamReader isr = new InputStreamReader(System.in);
	static BufferedReader br = new BufferedReader(isr);

	static int[] readIntArray() throws IOException {
		String[] v = br.readLine().split(" ");
		int[] ans = new int[v.length];

		for (int i = 0; i < ans.length; i++) {
			ans[i] = Integer.valueOf(v[i]);
		}

		return ans;
	}

	static int n, m, t;
	static int[] r;
	static TreeSet<String> sessions;
	static HashMap<Integer, Integer> logoutByID;
	static HashMap<Integer, Integer> userByRequest;
	static int currentID = 1;
	static String noSolution = "No solution";

	public static void main(String[] args) throws IOException {
		logoutByID = new HashMap<Integer, Integer>();
		userByRequest = new HashMap<Integer, Integer>();
		sessions = new TreeSet<String>();

		int[] l = readIntArray();
		n = l[0];
		m = l[1];
		t = l[2];
		if (n < m) {
			System.out.println(noSolution);
			return;
		}

		r = new int[n];
		for (int i = 0; i < n; i++) {
			r[i] = parse(br.readLine());
		}
		boolean reached = false;
		for (int i = 0; i < r.length; i++) {
			String k = getKey(r[i], 0);
			int alive = sessions.tailSet(k, true).size();
			if (alive < m) {
				sessions.add(getKey(r[i] + t - 1, currentID));
				logoutByID.put(currentID, r[i] + t - 1);
				userByRequest.put(i, currentID);
				currentID++;
			} else {
				reached = true;
				int logout = logoutByID.get(currentID - 1);
				logoutByID.put(currentID - 1, r[i] + t - 1);
				sessions.remove(getKey(logout, currentID - 1));
				sessions.add(getKey(r[i]+t-1, currentID - 1));
				userByRequest.put(i, currentID - 1);
			}
		}

		if(!reached) {
			System.out.println(noSolution);
			return;
		}

		System.out.println(currentID - 1);
		StringBuilder sb = new StringBuilder();
		for (int i = 0; i < n; i++) {
			if (sb.length() > 0) {
				sb.append('\n');
			}
			sb.append(userByRequest.get(i));
		}
		System.out.println(sb.toString());
	}

	static String getKey(int timestamp, int id) {
		return String.format("%010d", timestamp) + "-" + id;
	}

	private static int parse(String line) {
		String[] v = line.split(":");
		int ans = 0;
		ans = Integer.valueOf(v[0]) * 3600 + Integer.valueOf(v[1]) * 60 + Integer.valueOf(v[2]);

		return ans;
	}
}


#include <bits/stdc++.h>
using namespace std;
#define PII pair <int, int>
vector <int> timee [86405];
int parent[86405];
int findtimee[20005];
int ans[20005];
int findset (int a)
{
    if (parent[a]==0) return a;
    return parent[a]=findset(parent[a]);
}
void mergeset (int a, int b)
{
    int first=findset(a), second=findset(b);
    if (first==second) return;
    parent[first]=second;
}
int main()
{
    int n, M, T; cin >> n >> M >> T;
    for (int g=0; g<n; g++)
    {
        char a,b; cin >> a >> b;
        char c; cin >> c;
        char d,e; cin >> d >> e;
        char f; cin >> f;
        char gg,h; cin >> gg >> h;
        int ans=0;
        ans+=(10*(a-'0')+(b-'0'))*3600;
        ans+=(10*(d-'0')+(e-'0'))*60;
        ans+=(10*(gg-'0')+(h-'0'));
        timee[ans].push_back(g);
        findtimee[g]=ans;
    }
    deque <int> cur;
    int flag=0;
    for (int g=1; g<=86400; g++)
    {
        for (int y=0; y<timee[g].size(); y++)
        {
            cur.push_back(timee[g][y]);
        }
        while (cur.size())
        {
            int indice=cur[0];
            if (g-findtimee[indice]>=T) cur.erase(cur.begin());
            else break;
        }
        if (g==20007 && n>=50) cout << cur.size() << '\n';
        if (cur.size()<M) continue;
        if (cur.size()==M)
        {
            flag=1; continue;
        }
        flag=1;
        int erase=(int)cur.size()-M;
        int willremain=cur.size()-1-erase;
        for (int y=cur.size()-1; y>willremain; y--)
        {
            mergeset (cur[y],cur[willremain]);
        }
        cur.erase(cur.begin()+willremain+1, cur.end());
        assert(cur.size()<=M);
    }
    if (!flag)
    {
        cout << "No solution"; return 0;
    }
    map <int, int> checker;
    int answer=0;
    int current=1;
    for (int g=0; g<n; g++)
    {
        if (!parent[g])
        {
            answer++;
            ans[g]=current; current++;
        }
    }
    for (int g=0; g<n; g++)
    {
        if (parent[g])
        {
            ans[g]=ans[findset(g)];
        }
    }int orr=0;
    for (int g=0; g<n; g++)
    {
        if (findtimee[g]-20007>=0 && findtimee[g]-20007<T)
        {
            if (checker[ans[g]]) continue;
            checker[ans[g]]=1; orr++;
        }
    }if (n>=50)
    cout << orr << '\n';
    cout << answer << '\n';
    for (int g=0; g<n; g++) cout << ans[g] << '\n';
}


#include <bits/stdc++.h>
using namespace std;
#define PII pair <int, int>
vector <int> timee [86405];
int parent[86405];
int findtimee[20005];
int ans[20005];
int findset (int a)
{
    if (parent[a]==0) return a;
    return parent[a]=findset(parent[a]);
}
void mergeset (int a, int b)
{
    int first=findset(a), second=findset(b);
    if (first==second) return;
    parent[first]=second;
}
int main()
{
    int n, M, T; cin >> n >> M >> T;
    for (int g=0; g<n; g++)
    {
        char a,b; cin >> a >> b;
        char c; cin >> c;
        char d,e; cin >> d >> e;
        char f; cin >> f;
        char gg,h; cin >> gg >> h;
        int ans=0;
        ans+=(10*(a-'0')+(b-'0'))*3600;
        ans+=(10*(d-'0')+(e-'0'))*60;
        ans+=(10*(gg-'0')+(h-'0'));
        timee[ans].push_back(g);
        findtimee[g]=ans;
    }
    deque <int> cur;
    int flag=0;
    for (int g=1; g<=86400; g++)
    {
        for (int y=0; y<timee[g].size(); y++)
        {
            cur.push_back(timee[g][y]);
        }
        while (cur.size())
        {
            int indice=cur[0];
            if (g-findtimee[indice]>=T) cur.erase(cur.begin());
            else break;
        }
        if (g==5 && n==20000) cout << cur.size() << '\n';
        if (cur.size()<M) continue;
        if (cur.size()==M)
        {
            flag=1; continue;
        }
        flag=1;
        int erase=(int)cur.size()-M;
        int willremain=cur.size()-1-erase;
        for (int y=cur.size()-2; y>=willremain; y--)
        {
            mergeset (cur.back(),cur[y]);
        }
        cur.erase(cur.begin()+willremain, cur.end()-1);
    }
    if (!flag)
    {
        cout << "No solution"; return 0;
    }
    int answer=0;
    int current=1;
    for (int g=0; g<n; g++)
    {
        if (!parent[g])
        {
            answer++;
            ans[g]=current; current++;
        }
    }
    for (int g=0; g<n; g++)
    {
        if (parent[g])
        {
            ans[g]=ans[findset(g)];
        }
    }
    cout << answer << '\n';
    for (int g=0; g<n; g++) cout << ans[g] << '\n';
}


#include <bits/stdc++.h>
using namespace std;
#define PII pair <int, int>
vector <int> timee [86405];
int parent[86405];
int findtimee[20005];
int ans[20005];
int findset (int a)
{
    if (parent[a]==0) return a;
    return parent[a]=findset(parent[a]);
}
void mergeset (int a, int b)
{
    int first=findset(a), second=findset(b);
    if (first==second) return;
    parent[first]=second;
}
int main()
{
    int n, M, T; cin >> n >> M >> T;
    for (int g=0; g<n; g++)
    {
        char a,b; cin >> a >> b;
        char c; cin >> c;
        char d,e; cin >> d >> e;
        char f; cin >> f;
        char gg,h; cin >> gg >> h;
        int ans=0;
        ans+=(10*(a-'0')+(b-'0'))*3600;
        ans+=(10*(d-'0')+(e-'0'))*60;
        ans+=(10*(gg-'0')+(h-'0'));
        timee[ans].push_back(g);
        findtimee[g]=ans;
    }
    deque <int> cur;
    int flag=0;
    for (int g=1; g<=86400; g++)
    {
        for (int y=0; y<timee[g].size(); y++)
        {
            cur.push_back(timee[g][y]);
        }
        while (cur.size())
        {
            int indice=cur[0];
            if (g-findtimee[indice]>=T) cur.erase(cur.begin());
            else break;
        }
        if (cur.size()<M) continue;
        if (cur.size()==M)
        {
            flag=1; continue;
        }
        flag=1;
        int erase=(int)cur.size()-M;
        int willremain=cur.size()-1-erase;
        for (int y=cur.size()-2; y>=willremain; y--)
        {
            mergeset (cur.back(),cur[y]);
            if (g==5 && n==20000)
            cout << cur.back() << ' ' << cur[y] << '\n';
        }
        cur.erase(cur.begin()+willremain, cur.end()-1);
    }
    if (!flag)
    {
        cout << "No solution"; return 0;
    }
    int answer=0;
    int current=1;
    for (int g=0; g<n; g++)
    {
        if (!parent[g])
        {
            answer++;
            ans[g]=current; current++;
        }
    }
    for (int g=0; g<n; g++)
    {
        if (parent[g])
        {
            ans[g]=ans[findset(g)];
        }
    }
    cout << answer << '\n';
    for (int g=0; g<n; g++) cout << ans[g] << '\n';
}


#include <bits/stdc++.h>
using namespace std;
#define PII pair <int, int>
vector <int> timee [86405];
int parent[86405];
int findtimee[20005];
int ans[20005];
int findset (int a)
{
    if (parent[a]==-1) return a;
    return parent[a]=findset(parent[a]);
}
void mergeset (int a, int b)
{
    int first=findset(a), second=findset(b);
    if (first==second) return;
    parent[first]=second;
}
int main()
{
    int n, M, T; cin >> n >> M >> T;
    for (int g=0; g<n; g++)
    {parent[g]=-1;
        char a,b; cin >> a >> b;
        char c; cin >> c;
        char d,e; cin >> d >> e;
        char f; cin >> f;
        char gg,h; cin >> gg >> h;
        int ans=0;
        ans+=(10*(a-'0')+(b-'0'))*3600;
        ans+=(10*(d-'0')+(e-'0'))*60;
        ans+=(10*(gg-'0')+(h-'0'));
        timee[ans].push_back(g);
        findtimee[g]=ans;
    }
    deque <int> cur;
    int flag=0;
    for (int g=0; g<=86400; g++)
    {
        for (int y=0; y<timee[g].size(); y++)
        {
            cur.push_back(timee[g][y]);
        }
        while (cur.size())
        {
            int indice=cur[0];
            if (g-findtimee[indice]>=T) cur.erase(cur.begin());
            else break;
        }
        if (cur.size()<M) continue;
        if (cur.size()==M)
        {
            flag=1; continue;
        }
        flag=1;
        int erase=(int)cur.size()-M;
        int willremain=cur.size()-1-erase;
        for (int y=cur.size()-2; y>=willremain; y--)
        {
            mergeset (cur.back(),cur[y]);
        }
        cur.erase(cur.begin()+willremain, cur.end()-1);
    }
    if (!flag)
    {
        cout << "No solution"; return 0;
    }
    int answer=0;
    int current=1;
    for (int g=0; g<n; g++)
    {
        if (parent[g]==-1)
        {
            answer++;
            ans[g]=current; current++;
        }
    }
    for (int g=0; g<n; g++)
    {
        if (parent[g]!=-1)
        {
            ans[g]=ans[findset(g)];
        }
    }
    cout << answer << '\n';
    for (int g=0; g<n; g++) cout << ans[g] << '\n';
}


#include <bits/stdc++.h>
using namespace std;
#define PII pair <int, int>
vector <int> timee [86405];
int parent[86405];
int findtimee[20005];
int ans[20005];
int findset (int a)
{
    if (parent[a]==-1) return a;
    return parent[a]=findset(parent[a]);
}
void mergeset (int a, int b)
{
    int first=findset(a), second=findset(b);
    if (first==second) return;
    parent[first]=second;
}
int main()
{
    int n, M, T; cin >> n >> M >> T;
    for (int g=0; g<n; g++)
    {parent[g]=-1;
        char a,b; cin >> a >> b;
        char c; cin >> c;
        char d,e; cin >> d >> e;
        char f; cin >> f;
        char gg,h; cin >> gg >> h;
        int ans=0;
        ans+=(10*(a-'0')+(b-'0'))*3600;
        ans+=(10*(d-'0')+(e-'0'))*60;
        ans+=(10*(gg-'0')+(h-'0'));
        timee[ans].push_back(g);
        findtimee[g]=ans;
    }
    deque <int> cur;
    int flag=0;
    for (int g=1; g<=86400; g++)
    {
        for (int y=0; y<timee[g].size(); y++)
        {
            cur.push_back(timee[g][y]);
        }
        while (cur.size())
        {
            int indice=cur[0];
            if (g-findtimee[indice]>=T) cur.erase(cur.begin());
            else break;
        }
        if (cur.size()<M) continue;
        if (cur.size()==M)
        {
            flag=1; continue;
        }
        flag=1;
        int erase=(int)cur.size()-M;
        int willremain=cur.size()-1-erase;
        for (int y=cur.size()-2; y>=willremain; y--)
        {
            mergeset (cur.back(),cur[y]);
        }
        cur.erase(cur.begin()+willremain, cur.end()-1);
    }
    if (!flag)
    {
        cout << "No solution"; return 0;
    }
    int answer=0;
    int current=1;
    for (int g=0; g<n; g++)
    {
        if (parent[g]==-1)
        {
            answer++;
            ans[g]=current; current++;
        }
    }
    for (int g=0; g<n; g++)
    {
        if (parent[g]!=-1)
        {
            ans[g]=ans[findset(g)];
        }
    }
    cout << answer << '\n';
    for (int g=0; g<n; g++) cout << ans[g] << '\n';
}


#include <bits/stdc++.h>
using namespace std;
#define PII pair <int, int>
vector <int> timee [86405];
int parent[86405];
int findtimee[20005];
int ans[20005];
int findset (int a)
{
    if (parent[a]==0) return a;
    return parent[a]=findset(parent[a]);
}
void mergeset (int a, int b)
{
    int first=findset(a), second=findset(b);
    if (first==second) return;
    parent[first]=second;
}
int main()
{
    int n, M, T; cin >> n >> M >> T;
    for (int g=0; g<n; g++)
    {
        char a,b; cin >> a >> b;
        char c; cin >> c;
        char d,e; cin >> d >> e;
        char f; cin >> f;
        char gg,h; cin >> gg >> h;
        int ans=0;
        ans+=(10*(a-'0')+(b-'0'))*3600;
        ans+=(10*(d-'0')+(e-'0'))*60;
        ans+=(10*(gg-'0')+(h-'0'));
        timee[ans].push_back(g);
        cout << ans << '\n';
        findtimee[g]=ans;
    }
    deque <int> cur;
    int flag=0;
    for (int g=1; g<=86400; g++)
    {
        for (int y=0; y<timee[g].size(); y++)
        {
            cur.push_back(timee[g][y]);
        }
        while (cur.size())
        {
            int indice=cur[0];
            if (g-findtimee[indice]>=T) cur.erase(cur.begin());
            else break;
        }
        if (cur.size()<M) continue;
        if (cur.size()==M)
        {
            flag=1; continue;
        }
        flag=1;
        int erase=(int)cur.size()-M;
        int willremain=cur.size()-1-erase;
        for (int y=cur.size()-1; y>willremain; y--)
        {
            mergeset (cur[y],cur[willremain]);
        }
        cur.erase(cur.begin()+willremain+1, cur.end());
        assert(cur.size()<=M);
    }
    if (!flag)
    {
        cout << "No solution"; return 0;
    }
    int answer=0;
    int current=1;
    for (int g=0; g<n; g++)
    {
        if (!parent[g])
        {
            answer++;
            ans[g]=current; current++;
        }
    }
    for (int g=0; g<n; g++)
    {
        if (parent[g])
        {
            ans[g]=ans[findset(g)];
        }
    }
    cout << answer << '\n';
    for (int g=0; g<n; g++) cout << ans[g] << '\n';
}


#include <bits/stdc++.h>
using namespace std;
#define PII pair <int, int>
vector <int> timee [86405];
int parent[86405];
int findtimee[20005];
int ans[20005];
int findset (int a)
{
    if (parent[a]==0) return a;
    return parent[a]=findset(parent[a]);
}
void mergeset (int a, int b)
{
    int first=findset(a), second=findset(b);
    if (first==second) return;
    parent[first]=second;
}
int main()
{
    int n, M, T; cin >> n >> M >> T;
    for (int g=0; g<n; g++)
    {
        char a,b; cin >> a >> b;
        char c; cin >> c;
        char d,e; cin >> d >> e;
        char f; cin >> f;
        char gg,h; cin >> gg >> h;
        int ans=0;
        ans+=(10*(a-'0')+(b-'0'))*3600;
        ans+=(10*(d-'0')+(e-'0'))*60;
        ans+=(10*(gg-'0')+(h-'0'));
        timee[ans].push_back(g);
        findtimee[g]=ans;
    }
    deque <int> cur;
    int flag=0;
    for (int g=1; g<=86400; g++)
    {
        for (int y=0; y<timee[g].size(); y++)
        {
            cur.push_back(timee[g][y]);
        }
        while (cur.size())
        {
            int indice=cur[0];
            if (g-findtimee[indice]>=T) cur.erase(cur.begin());
            else break;
        }
        if (g==20007 && n>=50) cout << cur.size() << '\n';
        if (cur.size()<M) continue;
        if (cur.size()==M)
        {
            flag=1; continue;
        }
        flag=1;
        int erase=(int)cur.size()-M;
        int willremain=cur.size()-1-erase;
        for (int y=cur.size()-1; y>willremain; y--)
        {
            mergeset (cur[y],cur[willremain]);
        }
        cur.erase(cur.begin()+willremain+1, cur.end());
        assert(cur.size()<=M);
    }
    if (!flag)
    {
        cout << "No solution"; return 0;
    }
    map <int, int> checker;
    int answer=0;
    int current=1;
    for (int g=0; g<n; g++)
    {
        if (!parent[g])
        {
            answer++;
            ans[g]=current; current++;
        }
    }
    for (int g=0; g<n; g++)
    {
        if (parent[g])
        {
            ans[g]=ans[findset(g)];
        }
    }int orr=0;
    for (int g=0; g<n; g++)
    {
        if (20007-findtimee[g]>=0 && 20007-findtimee[g]<T)
        {
            if (checker[ans[g]]) continue;
            checker[ans[g]]=1; orr++;
        }
    }if (n>=50)
    cout << orr << '\n';
    cout << answer << '\n';
    for (int g=0; g<n; g++) cout << ans[g] << '\n';
}


#include <bits/stdc++.h>
using namespace std;
#define PII pair <int, int>
vector <int> timee [86405];
int parent[86405];
int findtimee[20005];
int ans[20005];
int findset (int a)
{
    if (parent[a]==0) return a;
    return parent[a]=findset(parent[a]);
}
void mergeset (int a, int b)
{
    int first=findset(a), second=findset(b);
    if (first==second) return;
    parent[first]=second;
}
int main()
{
    int n, M, T; cin >> n >> M >> T;
    for (int g=0; g<n; g++)
    {
        char a,b; cin >> a >> b;
        char c; cin >> c;
        char d,e; cin >> d >> e;
        char f; cin >> f;
        char gg,h; cin >> gg >> h;
        int ans=0;
        ans+=(10*(a-'0')+(b-'0'))*3600;
        ans+=(10*(d-'0')+(e-'0'))*60;
        ans+=(10*(gg-'0')+(h-'0'));
        timee[ans].push_back(g);
        findtimee[g]=ans;
    }
    deque <int> cur;
    int flag=0;
    for (int g=1; g<=86400; g++)
    {
        for (int y=0; y<timee[g].size(); y++)
        {
            cur.push_back(timee[g][y]);
        }
        while (cur.size())
        {
            int indice=cur[0];
            if (g-findtimee[indice]>=T) cur.erase(cur.begin());
            else break;
        }
        if (g==20007 && n>=50) cout << cur.size() << '\n';
        if (cur.size()<M) continue;
        if (cur.size()==M)
        {
            flag=1; continue;
        }
        flag=1;
        int erase=(int)cur.size()-M;
        int willremain=cur.size()-1-erase;
        for (int y=cur.size()-1; y>willremain; y--)
        {
            mergeset (cur[y],cur[willremain]);
        }
        cur.erase(cur.begin()+willremain+1, cur.end());
        assert(cur.size()<=M);
    }
    if (!flag)
    {
        cout << "No solution"; return 0;
    }
    int answer=0;
    int current=1;
    for (int g=0; g<n; g++)
    {
        if (!parent[g])
        {
            answer++;
            ans[g]=current; current++;
        }
    }
    for (int g=0; g<n; g++)
    {
        if (parent[g])
        {
            ans[g]=ans[findset(g)];
        }
    }
    cout << answer << '\n';
    for (int g=0; g<n; g++) cout << ans[g] << '\n';
}


#include <bits/stdc++.h>
using namespace std;
#define PII pair <int, int>
vector <int> timee [86405];
int parent[86405];
int findtimee[20005];
int ans[20005];
int findset (int a)
{
    if (parent[a]==0) return a;
    return parent[a]=findset(parent[a]);
}
void mergeset (int a, int b)
{
    int first=findset(a), second=findset(b);
    if (first==second) return;
    parent[first]=second;
}
int main()
{
    int n, M, T; cin >> n >> M >> T;
    for (int g=0; g<n; g++)
    {
        char a,b; cin >> a >> b;
        char c; cin >> c;
        char d,e; cin >> d >> e;
        char f; cin >> f;
        char gg,h; cin >> gg >> h;
        int ans=0;
        ans+=(10*(a-'0')+(b-'0'))*3600;
        ans+=(10*(d-'0')+(e-'0'))*60;
        ans+=(10*(gg-'0')+(h-'0'));
        timee[ans].push_back(g);
        findtimee[g]=ans;
    }
    deque <int> cur;
    int flag=0;
    for (int g=1; g<=86400; g++)
    {
        for (int y=0; y<timee[g].size(); y++)
        {
            cur.push_back(timee[g][y]);
        }
        while (cur.size())
        {
            int indice=cur[0];
            if (g-findtimee[indice]>=T) cur.erase(cur.begin());
            else break;
        }
        if (cur.size()<M) continue;
        if (cur.size()==M)
        {
            flag=1; continue;
        }
        flag=1;
        int erase=(int)cur.size()-M;
        int willremain=cur.size()-1-erase;
                if (g==5 && n==20000) cout << willremain << '\n';

        for (int y=cur.size()-2; y>=willremain; y--)
        {
            mergeset (cur.back(),cur[y]);
        }
        cur.erase(cur.begin()+willremain, cur.end()-1);
    }
    if (!flag)
    {
        cout << "No solution"; return 0;
    }
    int answer=0;
    int current=1;
    for (int g=0; g<n; g++)
    {
        if (!parent[g])
        {
            answer++;
            ans[g]=current; current++;
        }
    }
    for (int g=0; g<n; g++)
    {
        if (parent[g])
        {
            ans[g]=ans[findset(g)];
        }
    }
    cout << answer << '\n';
    for (int g=0; g<n; g++) cout << ans[g] << '\n';
}


#include <bits/stdc++.h>
using namespace std;
#define PII pair <int, int>
vector <int> timee [86405];
int parent[86405];
int findtimee[20005];
int ans[20005];
int findset (int a)
{
    if (parent[a]==0) return a;
    return parent[a]=findset(parent[a]);
}
void mergeset (int a, int b)
{
    int first=findset(a), second=findset(b);
    if (first==second) return;
    parent[first]=second;
}
int main()
{
    int n, M, T; cin >> n >> M >> T;
    for (int g=0; g<n; g++)
    {
        char a,b; cin >> a >> b;
        char c; cin >> c;
        char d,e; cin >> d >> e;
        char f; cin >> f;
        char gg,h; cin >> gg >> h;
        int ans=0;
        ans+=(10*(a-'0')+(b-'0'))*3600;
        ans+=(10*(d-'0')+(e-'0'))*60;
        ans+=(10*(gg-'0')+(h-'0'));
        timee[ans].push_back(g);
        findtimee[g]=ans;
    }
    deque <int> cur;
    int flag=0;
    for (int g=1; g<=86400; g++)
    {
        for (int y=0; y<timee[g].size(); y++)
        {
            cur.push_back(timee[g][y]);
        }
        while (cur.size())
        {
            int indice=cur[0];
            if (g-findtimee[indice]>=T) cur.erase(cur.begin());
            else break;
        }
        if (cur.size()<M) continue;
        if (cur.size()==M)
        {
            flag=1; continue;
        }
        flag=1;
        int erase=(int)cur.size()-M;
        int willremain=cur.size()-1-erase;
        for (int y=cur.size()-1; y>willremain; y--)
        {
            mergeset (cur[y],cur[willremain]);
        }
        cur.erase(cur.begin()+willremain+1, cur.end());
    }
    if (!flag)
    {
        cout << "No solution"; return 0;
    }
    int answer=0;
    int current=1;
    for (int g=0; g<n; g++)
    {
        if (!parent[g])
        {
            answer++;
            ans[g]=current; current++;
        }
    }
    for (int g=0; g<n; g++)
    {
        if (parent[g])
        {
            ans[g]=ans[findset(g)];
        }
    }
    cout << answer << '\n';
    for (int g=0; g<n; g++) cout << ans[g] << '\n';
}


#include <bits/stdc++.h>
using namespace std;
#define PII pair <int, int>
vector <int> timee [86405];
int parent[86405];
int findtimee[20005];
int ans[20005];
int findset (int a)
{
    if (parent[a]==0) return a;
    return parent[a]=findset(parent[a]);
}
void mergeset (int a, int b)
{
    int first=findset(a), second=findset(b);
    if (first==second) return;
    parent[first]=second;
}
int main()
{
    int n, M, T; cin >> n >> M >> T;
    for (int g=0; g<n; g++)
    {
        char a,b; cin >> a >> b;
        char c; cin >> c;
        char d,e; cin >> d >> e;
        char f; cin >> f;
        char gg,h; cin >> gg >> h;
        int ans=0;
        ans+=(10*(a-'0')+(b-'0'))*3600;
        ans+=(10*(d-'0')+(e-'0'))*60;
        ans+=(10*(gg-'0')+(h-'0'));
        timee[ans].push_back(g);
        findtimee[g]=ans;
    }
    deque <int> cur;
    int flag=0;
    for (int g=1; g<=86400; g++)
    {
        for (int y=0; y<timee[g].size(); y++)
        {
            cur.push_back(timee[g][y]);
        }
        while (cur.size())
        {
            int indice=cur[0];
            if (g-findtimee[indice]>=T) cur.erase(cur.begin());
            else break;
        }
        if (g==20007 && n>=50) cout << cur.size() << '\n';
        if (cur.size()<M) continue;
        if (cur.size()==M)
        {
            flag=1; continue;
        }
        flag=1;
        int erase=(int)cur.size()-M;
        int willremain=cur.size()-1-erase;
        for (int y=cur.size()-1; y>willremain; y--)
        {
            mergeset (cur[y],cur[willremain]);
        }
        cur.erase(cur.begin()+willremain+1, cur.end());
        assert(cur.size()<=M);
    }
    if (!flag)
    {
        cout << "No solution"; return 0;
    }
    map <int, int> checker;
    int answer=0;
    int current=1;
    for (int g=0; g<n; g++)
    {
        if (!parent[g])
        {
            answer++;
            ans[g]=current; current++;
        }
    }
    for (int g=0; g<n; g++)
    {
        if (parent[g])
        {
            ans[g]=ans[findset(g)];
        }
    }int orr=0;
    for (int g=0; g<n; g++)
    {
        if (findtimee[g]-20007>=0 && findtimee[g]-20007<T)
        {
            if (checker[ans[g]]) continue;
            checker[ans[g]]=1; orr++;
        }
    }
    cout << orr << '\n';
    cout << answer << '\n';
    for (int g=0; g<n; g++) cout << ans[g] << '\n';
}


#include <bits/stdc++.h>
using namespace std;
#define PII pair <int, int>
vector <int> timee [86405];
int parent[86405];
int findtimee[20005];
int ans[20005];
int findset (int a)
{
    if (parent[a]==0) return a;
    return parent[a]=findset(parent[a]);
}
void mergeset (int a, int b)
{
    int first=findset(a), second=findset(b);
    if (first==second) return;
    parent[first]=second;
}
int main()
{
    int n, M, T; cin >> n >> M >> T;
    for (int g=0; g<n; g++)
    {
        char a,b; cin >> a >> b;
        char c; cin >> c;
        char d,e; cin >> d >> e;
        char f; cin >> f;
        char gg,h; cin >> gg >> h;
        int ans=0;
        ans+=(10*(a-'0')+(b-'0'))*3600;
        ans+=(10*(d-'0')+(e-'0'))*60;
        ans+=(10*(gg-'0')+(h-'0'));
        timee[ans].push_back(g);
        findtimee[g]=ans;
    }
    deque <int> cur;
    int flag=0;
    for (int g=1; g<=86400; g++)
    {
        for (int y=0; y<timee[g].size(); y++)
        {
            cur.push_back(timee[g][y]);
        }
        while (cur.size())
        {
            int indice=cur[0];
            if (g-findtimee[indice]>=T) cur.erase(cur.begin());
            else break;
        }
        if (cur.size()<M) continue;
        if (cur.size()==M)
        {
            flag=1; continue;
        }
        flag=1;
        int erase=(int)cur.size()-M;
        int willremain=cur.size()-1-erase;
        for (int y=cur.size()-1; y>willremain; y--)
        {
            mergeset (cur[y],cur[willremain]);
        }
        cur.erase(cur.begin()+willremain+1, cur.end());
        assert(cur.size()>M);
    }
    if (!flag)
    {
        cout << "No solution"; return 0;
    }
    int answer=0;
    int current=1;
    for (int g=0; g<n; g++)
    {
        if (!parent[g])
        {
            answer++;
            ans[g]=current; current++;
        }
    }
    for (int g=0; g<n; g++)
    {
        if (parent[g])
        {
            ans[g]=ans[findset(g)];
        }
    }
    cout << answer << '\n';
    for (int g=0; g<n; g++) cout << ans[g] << '\n';
}


#include <bits/stdc++.h>
using namespace std;
#define PII pair <int, int>
vector <int> timee [86405];
int parent[86405];
int findtimee[20005];
int ans[20005];
int findset (int a)
{
    if (parent[a]==0) return a;
    return parent[a]=findset(parent[a]);
}
void mergeset (int a, int b)
{
    int first=findset(a), second=findset(b);
    if (first==second) return;
    parent[first]=second;
}
int main()
{
    int n, M, T; cin >> n >> M >> T;
    for (int g=0; g<n; g++)
    {
        char a,b; cin >> a >> b;
        char c; cin >> c;
        char d,e; cin >> d >> e;
        char f; cin >> f;
        char gg,h; cin >> gg >> h;
        int ans=0;
        ans+=(10*(a-'0')+(b-'0'))*3600;
        ans+=(10*(d-'0')+(e-'0'))*60;
        ans+=(10*(gg-'0')+(h-'0'));
        timee[ans].push_back(g);
        findtimee[g]=ans;
    }
    deque <int> cur;
    int flag=0;
    for (int g=1; g<=86400; g++)
    {
        for (int y=0; y<timee[g].size(); y++)
        {
            cur.push_back(timee[g][y]);
        }
        while (cur.size())
        {
            int indice=cur[0];
            if (g-findtimee[indice]>=T) cur.erase(cur.begin());
            else break;
        }
        if (g==5 && n==20000 && T==325) cout << cur.size() << '\n';
        if (cur.size()<M) continue;
        if (cur.size()==M)
        {
            flag=1; continue;
        }
        flag=1;
        int erase=(int)cur.size()-M;
        int willremain=cur.size()-1-erase;
        for (int y=cur.size()-2; y>=willremain; y--)
        {
            mergeset (cur.back(),cur[y]);
        }
        cur.erase(cur.begin()+willremain, cur.end()-1);
    }
    if (!flag)
    {
        cout << "No solution"; return 0;
    }
    int answer=0;
    int current=1;
    for (int g=0; g<n; g++)
    {
        if (!parent[g])
        {
            answer++;
            ans[g]=current; current++;
        }
    }
    for (int g=0; g<n; g++)
    {
        if (parent[g])
        {
            ans[g]=ans[findset(g)];
        }
    }
    cout << answer << '\n';
    for (int g=0; g<n; g++) cout << ans[g] << '\n';
}


#include <bits/stdc++.h>
using namespace std;
#define PII pair <int, int>
vector <int> timee [86405];
int parent[86405];
int findtimee[20005];
int ans[20005];
int findset (int a)
{
    if (parent[a]==0) return a;
    return parent[a]=findset(parent[a]);
}
void mergeset (int a, int b)
{
    int first=findset(a), second=findset(b);
    if (first==second) return;
    parent[first]=second;
}
int main()
{
    int n, M, T; cin >> n >> M >> T;
    for (int g=0; g<n; g++)
    {
        char a,b; cin >> a >> b;
        char c; cin >> c;
        char d,e; cin >> d >> e;
        char f; cin >> f;
        char gg,h; cin >> gg >> h;
        int ans=0;
        ans+=(10*(a-'0')+(b-'0'))*3600;
        ans+=(10*(d-'0')+(e-'0'))*60;
        ans+=(10*(gg-'0')+(h-'0'));
        timee[ans].push_back(g);
        findtimee[g]=ans;
    }
    deque <int> cur;
    int flag=0;
    for (int g=1; g<=86400; g++)
    {
        for (int y=0; y<timee[g].size(); y++)
        {
            cur.push_back(timee[g][y]);
        }
        while (cur.size())
        {
            int indice=cur[0];
            if (g-findtimee[indice]>=T) cur.erase(cur.begin());
            else break;
        }
        if (cur.size()<M) continue;
        if (cur.size()==M)
        {
            flag=1; continue;
        }
        flag=1;
        int erase=(int)cur.size()-M;
        int willremain=cur.size()-1-erase;
        for (int y=cur.size()-1; y>willremain; y--)
        {
            mergeset (cur[y],cur[willremain]);
        }
        cur.erase(cur.begin()+willremain+1, cur.end());
        assert(cur.size()<=M);
    }
    if (!flag)
    {
        cout << "No solution"; return 0;
    }
    int answer=0;
    int current=1;
    for (int g=0; g<n; g++)
    {
        if (!parent[g])
        {
            answer++;
            ans[g]=current; current++;
        }
    }
    for (int g=0; g<n; g++)
    {
        if (parent[g])
        {
            ans[g]=ans[findset(g)];
        }
    }
    cout << answer << '\n';
    for (int g=0; g<n; g++) cout << ans[g] << '\n';
}


#include <bits/stdc++.h>
using namespace std;
#define PII pair <int, int>
vector <int> timee [86405];
int parent[86405];
int findtimee[20005];
int ans[20005];
int findset (int a)
{
    if (parent[a]==0) return a;
    return parent[a]=findset(parent[a]);
}
void mergeset (int a, int b)
{
    int first=findset(a), second=findset(b);
    if (first==second) return;
    parent[first]=second;
}
int main()
{
    int n, M, T; cin >> n >> M >> T;
    for (int g=0; g<n; g++)
    {
        char a,b; cin >> a >> b;
        char c; cin >> c;
        char d,e; cin >> d >> e;
        char f; cin >> f;
        char gg,h; cin >> gg >> h;
        int ans=0;
        ans+=(10*(a-'0')+(b-'0'))*3600;
        ans+=(10*(d-'0')+(e-'0'))*60;
        ans+=(10*(gg-'0')+(h-'0'));
        timee[ans].push_back(g);
        findtimee[g]=ans;
    }
    deque <int> cur;
    int flag=0;
    for (int g=1; g<=86400; g++)
    {
        for (int y=0; y<timee[g].size(); y++)
        {
            cur.push_back(timee[g][y]);
        }
        while (cur.size())
        {
            int indice=cur[0];
            if (g-findtimee[indice]>=T) cur.erase(cur.begin());
            else break;
        }
        if (g==20007) cout << cur.size() << '\n';
        if (cur.size()<M) continue;
        if (cur.size()==M)
        {
            flag=1; continue;
        }
        flag=1;
        int erase=(int)cur.size()-M;
        int willremain=cur.size()-1-erase;
        for (int y=cur.size()-1; y>willremain; y--)
        {
            mergeset (cur[y],cur[willremain]);
        }
        cur.erase(cur.begin()+willremain+1, cur.end());
        assert(cur.size()<=M);
    }
    if (!flag)
    {
        cout << "No solution"; return 0;
    }
    int answer=0;
    int current=1;
    for (int g=0; g<n; g++)
    {
        if (!parent[g])
        {
            answer++;
            ans[g]=current; current++;
        }
    }
    for (int g=0; g<n; g++)
    {
        if (parent[g])
        {
            ans[g]=ans[findset(g)];
        }
    }
    cout << answer << '\n';
    for (int g=0; g<n; g++) cout << ans[g] << '\n';
}


#include <bits/stdc++.h>
using namespace std;
#define PII pair <int, int>
vector <int> timee [86405];
int parent[86405];
int findtimee[20005];
int ans[20005];
int findset (int a)
{
    if (parent[a]==0) return a;
    return parent[a]=findset(parent[a]);
}
void mergeset (int a, int b)
{
    int first=findset(a), second=findset(b);
    if (first==second) return;
    parent[first]=second;
}
int main()
{
    int n, M, T; cin >> n >> M >> T;
    for (int g=0; g<n; g++)
    {
        char a,b; cin >> a >> b;
        char c; cin >> c;
        char d,e; cin >> d >> e;
        char f; cin >> f;
        char gg,h; cin >> gg >> h;
        int ans=0;
        ans+=(10*(a-'0')+(b-'0'))*3600;
        ans+=(10*(d-'0')+(e-'0'))*60;
        ans+=(10*(gg-'0')+(h-'0'));
        timee[ans].push_back(g);
        findtimee[g]=ans;
    }
    deque <int> cur;
    int flag=0;
    for (int g=1; g<=86400; g++)
    {
        for (int y=0; y<timee[g].size(); y++)
        {
            cur.push_back(timee[g][y]);
        }
        while (cur.size())
        {
            int indice=cur[0];
            if (g-findtimee[indice]>=T) cur.erase(cur.begin());
            else break;
        }
        if (g==20007 && n>=10000) cout << cur.size() << '\n';
        if (cur.size()<M) continue;
        if (cur.size()==M)
        {
            flag=1; continue;
        }
        flag=1;
        int erase=(int)cur.size()-M;
        int willremain=cur.size()-1-erase;
        for (int y=cur.size()-1; y>willremain; y--)
        {
            mergeset (cur[y],cur[willremain]);
        }
        cur.erase(cur.begin()+willremain+1, cur.end());
        assert(cur.size()<=M);
    }
    if (!flag)
    {
        cout << "No solution"; return 0;
    }
    int answer=0;
    int current=1;
    for (int g=0; g<n; g++)
    {
        if (!parent[g])
        {
            answer++;
            ans[g]=current; current++;
        }
    }
    for (int g=0; g<n; g++)
    {
        if (parent[g])
        {
            ans[g]=ans[findset(g)];
        }
    }
    cout << answer << '\n';
    for (int g=0; g<n; g++) cout << ans[g] << '\n';
}


#include <bits/stdc++.h>
using namespace std;
#define PII pair <int, int>
vector <int> timee [86405];
int parent[86405];
int findtimee[20005];
int ans[20005];
int findset (int a)
{
    if (parent[a]==0) return a;
    return parent[a]=findset(parent[a]);
}
void mergeset (int a, int b)
{
    int first=findset(a), second=findset(b);
    if (first==second) return;
    parent[first]=second;
}
int main()
{
    int n, M, T; cin >> n >> M >> T;
    for (int g=0; g<n; g++)
    {
        char a,b; cin >> a >> b;
        char c; cin >> c;
        char d,e; cin >> d >> e;
        char f; cin >> f;
        char gg,h; cin >> gg >> h;
        int ans=0;
        ans+=(10*(a-'0')+(b-'0'))*3600;
        ans+=(10*(d-'0')+(e-'0'))*60;
        ans+=(10*(gg-'0')+(h-'0'));
        timee[ans].push_back(g);
        findtimee[g]=ans;
    }
    deque <int> cur;
    int flag=0;
    for (int g=1; g<=86400; g++)
    {
        for (int y=0; y<timee[g].size(); y++)
        {
            cur.push_back(timee[g][y]);
        }
        while (cur.size())
        {
            int indice=cur[0];
            if (g-findtimee[indice]>=T) cur.erase(cur.begin());
            else break;
        }
        if (cur.size()<M) continue;
        if (cur.size()==M)
        {
            flag=1; continue;
        }
        flag=1;
        int erase=(int)cur.size()-M;
        int willremain=cur.size()-1-erase;
        for (int y=cur.size()-1; y>willremain; y--)
        {
            mergeset (cur[y],cur[willremain]);
        }
        cur.erase(cur.begin()+willremain+1, cur.end());
        if (g==20007) cout << cur.size() << '\n';
        assert(cur.size()<=M);
    }
    if (!flag)
    {
        cout << "No solution"; return 0;
    }
    int answer=0;
    int current=1;
    for (int g=0; g<n; g++)
    {
        if (!parent[g])
        {
            answer++;
            ans[g]=current; current++;
        }
    }
    for (int g=0; g<n; g++)
    {
        if (parent[g])
        {
            ans[g]=ans[findset(g)];
        }
    }
    cout << answer << '\n';
    for (int g=0; g<n; g++) cout << ans[g] << '\n';
}


#include <bits/stdc++.h>
using namespace std;
#define PII pair <int, int>
vector <int> timee [86405];
int parent[86405];
int findtimee[20005];
int ans[20005];
int findset (int a)
{
    if (parent[a]==0) return a;
    return parent[a]=findset(parent[a]);
}
void mergeset (int a, int b)
{
    int first=findset(a), second=findset(b);
    if (first==second) return;
    parent[first]=second;
}
int main()
{
    int n, M, T; cin >> n >> M >> T;
    for (int g=0; g<n; g++)
    {
        char a,b; cin >> a >> b;
        char c; cin >> c;
        char d,e; cin >> d >> e;
        char f; cin >> f;
        char gg,h; cin >> gg >> h;
        int ans=0;
        ans+=(10*(a-'0')+(b-'0'))*3600;
        ans+=(10*(d-'0')+(e-'0'))*60;
        ans+=(10*(gg-'0')+(h-'0'));
        timee[ans].push_back(g);
        findtimee[g]=ans;
    }
    deque <int> cur;
    int flag=0;
    for (int g=1; g<=86400; g++)
    {
        for (int y=0; y<timee[g].size(); y++)
        {
            cur.push_back(timee[g][y]);
        }
        while (cur.size())
        {
            int indice=cur[0];
            if (g-findtimee[indice]>=T) cur.erase(cur.begin());
            else break;
        }
        if (cur.size()<M) continue;
        if (cur.size()==M)
        {
            flag=1; continue;
        }
        flag=1;
        int erase=(int)cur.size()-M;
        int willremain=cur.size()-1-erase;
        for (int y=cur.size()-2; y>=willremain; y--)
        {
            mergeset (cur.back(),cur[y]);
        }
        cur.erase(cur.begin()+willremain, cur.end()-1);
    }
    if (!flag)
    {
        cout << "No solution"; return 0;
    }
    int answer=0;
    int current=1;
    for (int g=0; g<n; g++)
    {
        if (!parent[g])
        {
            answer++;
            ans[g]=current; current++;
        }
    }
    for (int g=0; g<n; g++)
    {
        if (parent[g])
        {
            ans[g]=ans[findset(g)];
        }
    }
    cout << answer << '\n';
    for (int g=0; g<n; g++) cout << ans[g] << '\n';
}


#include <stdio.h>
#include <map>

std::map<int, int> chk;
int N,M,T,R,A[20002];

int main()
{
    scanf ("%d %d %d",&N,&M,&T);
    bool good = 0;
    for (int i=0;i<N;i++){
        int h,m,s;
        scanf ("%d:%d:%d",&h,&m,&s);
        int p = h * 3600 + m * 60 + s;

        while (!chk.empty() && chk.begin()->first + T <= p) chk.erase(chk.begin());
        if (chk.size() == M){
            int last = chk.end().operator--()->second;
            chk.erase(chk.end().operator--());
            A[i] = chk[p] = last;
            good = 1;
        }
        else A[i] = chk[p] = ++R;
    }

    if (good){
        printf ("%d\n",R);
        for (int i=0;i<N;i++) printf ("%d\n",A[i]);
    }
    else puts("No solution");

    return 0;
}


#include <stdio.h>
#include <map>
using namespace std;

multimap<int, int> chk;
int N,M,T,R,A[20002];

int main()
{
    scanf ("%d %d %d",&N,&M,&T);
    bool good = 0;
    for (int i=0;i<N;i++){
        int h,m,s;
        scanf ("%d:%d:%d",&h,&m,&s);
        int p = h * 3600 + m * 60 + s;

        while (!chk.empty() && chk.begin()->first + T <= p) chk.erase(chk.begin());
        if (chk.size() == M){
            int last = chk.end().operator--()->second;
            chk.erase(chk.end().operator--());
            A[i] = last;
            chk.insert(make_pair(p,last));
        }
        else{
            A[i] = ++R;
            chk.insert(make_pair(p,R));
        }

        if (chk.size() == M) good = 1;
    }

    if (good){
        printf ("%d\n",R);
        for (int i=0;i<N;i++) printf ("%d\n",A[i]);
    }
    else puts("No solution");

    return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define long int64_t

int A[20010], I[20010];
int n, m, p;

int get_time ()
{
	char t[10];
	scanf("%s", t);

	return ((t[0] - '0') * 10 + (t[1] - '0')) * 60 * 60 +
		   ((t[3] - '0') * 10 + (t[4] - '0')) * 60 +
		    (t[6] - '0') * 10 + (t[7] - '0');
}

inline void remv (map<int,int> &T, int x)
{
	if (--T[x] == 0) T.erase(x);
}

void enter ()
{
	scanf("%d%d%d", &n, &m, &p);
	for (int i = 1; i <= n; ++i) A[i] = get_time();
}

void solve ()
{
	map<int,int> T;
	bool peaked = false;
	int i, j, cnt = 0;

	for (i = j = 1; i <= n; ++i)
	{
		while (A[j] + p <= A[i]) remv(T, I[j++]);

		if (T.size() < m) I[i] = ++cnt;
		else
			I[i] = I[i - 1];

		++T[I[i]];
		if (T.size() == m) peaked = true;
	}

	if (peaked)
	{
		printf("%d\n", cnt);
		for (int i = 1; i <= n; ++i) printf("%d\n", I[i]);
	} else
		puts("No solution");
}

int main ()
{
	#ifdef isMyPC
		freopen("test.inp", "r", stdin);
	#endif

	enter ();
	solve ();

	return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define long int64_t

int A[20010], I[20010];
int n, m, p;

int get_time ()
{
	char t[10];
	scanf("%s", t);

	return ((t[0] - '0') * 10 + (t[1] - '0')) * 60 * 60 +
		   ((t[3] - '0') * 10 + (t[4] - '0')) * 60 +
		    (t[6] - '0') * 10 + (t[7] - '0');
}

void enter ()
{
	scanf("%d%d%d", &n, &m, &p);
	for (int i = 1; i <= n; ++i) A[i] = get_time();
}

void solve ()
{
	bool peaked = false;
	int i, j, cnt = 0;

	for (i = j = 1; i <= n; ++i)
	{
		while (j < i && A[j] + p <= A[i]) ++j;

		if (i - j < m)
		{
			I[i] = ++cnt;
			if (i - j + 1 == m) peaked = true;
		} else
			I[i] = I[i - 1];
	}

	if (peaked)
	{
		printf("%d\n", cnt);
		for (int i = 1; i <= n; ++i) printf("%d\n", I[i]);
	} else
		puts("No solution");
}

int main ()
{
	#ifdef isMyPC
		freopen("test.inp", "r", stdin);
	#endif

	enter ();
	solve ();

	return 0;
}


#include <bits/stdc++.h>

#ifdef PEYEK
	#define debugln {printf("----OK----\n");}
	#define debug(...) {printf(__VA_ARGS__);}
	#define debugs(...) {printf(":::::--->> ");printf(__VA_ARGS__);}
	#define TIME() printf("%.3lf\n",clock()/(double)CLOCKS_PER_SEC)
#else
	#define debugln {}
	#define debug(...) {}
	#define debugs(...) {}
	#define TIME() {}
#endif

#define __INIT_CC__ ios::sync_with_stdio(false); \
	cin.tie(0);

#ifdef __WIN32__
	char getchar_unlocked() {return getchar();}
#endif

#define FOR(_i,_n,_m) for(int (_i)=(_n),_t=(_m);_i<(_t);++(_i))
#define FORN(_i,_n,_m) for(int (_i)=(_n),_t=(_m);_i<=(_t);++(_i))
#define FORD(_i,_n,_m) for(int (_i)=(_n),_t=(_m);_i>=(_t);--(_i))
#define FORLL(_i,_n,_m) for(long long (_i)=(_n),_t=(_m);_i<(_t);++(_i))
#define FORNLL(_i,_n,_m) for(long long (_i)=(_n),_t=(_m);(_i)<=(_t);++(_i))
#define FORDLL(_i,_n,_m) for(long long (_i)=(_n),_t=(_m);(_i)>=(_t);--(_i))
#define FOREACH(_i,_a) for (__typeof(_a.begin()) _i=_a.begin();_i!=_a.end();++_i)
#define RESET(_a,_value) memset(_a,_value,sizeof(_a))
#define pb push_back
#define ppb pop_back
#define pf push_front
#define ppf pop_front
#define ff first
#define ss second
#define mp make_pair
#define SIZE(_a) (int)_a.size()
#define VSORT(_a) sort(_a.begin(),_a.end())
#define SSORT(_a,_val) sort(_a,_a+(_val))
#define ALL(_a) _a.begin(),_a.end()
#define mt make_tuple
#define _get(_tuple,_i) get<_i>(_tuple)
#define eb emplace_back

using namespace std;

const int dr[]={ 1, 0,-1, 0, 1, 1,-1,-1};
const int dc[]={ 0, 1, 0,-1, 1,-1,-1, 1};
const double eps=1e-9;
typedef vector<int> vi;
typedef pair<int,int> ii;
typedef vector<ii> vii;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<ll,ll> pll;
typedef vector<pll> vpll;
typedef vector<ll> vll;
typedef pair<double,double> pdd;
typedef vector<pdd> vpdd;
const int INF=0x7FFFFFFF;
const ll INFLL=0x7FFFFFFFFFFFFFFFLL;
const double pi=acos(-1);

template <class T> T take(queue<T> &O) {T tmp=O.front();O.pop();return tmp;}
template <class T> T take(stack<T> &O) {T tmp=O.top();O.pop();return tmp;}
template <class T> T take(priority_queue<T> &O) {T tmp=O.top();O.pop();return tmp;}
template <class T> inline void getint(T &num)
{
	bool neg=0;
	num=0;
	char c;
	while ((c=getchar_unlocked()) && (!isdigit(c) && c!='-'));
	if (c=='-')
	{
		neg=1;
		c=getchar_unlocked();
	}
	do num=num*10+c-'0';
	while ((c=getchar_unlocked()) && isdigit(c));
	num*=(neg)?-1:1;
}

template <class T> inline bool inRange(T z, T a, T b){return a <= z && z <= b;}

void OPEN(string in="input.txt",string out="output.txt")
{
	freopen(in.c_str(),"r",stdin);
	freopen(out.c_str(),"w",stdout);
	return ;
}

//using sokokaleb's template v3.0

typedef pair<ii, int> i3;

int n, m, T;
vector<i3> seg;
int idseg[20005];
bitset<20005> ada;
set<int> SET;
priority_queue<ii> PQ;

int main(int argc, const char *argv[])
{
	getint(n);getint(m);getint(T);
	FOR (i,0,n)
	{
		int h,m,s;
		getint(h);getint(m);getint(s);
		s = h * 3600 + m * 60 + s;
		seg.pb(mp(mp(s, s + T - 1), i));
	}
	VSORT(seg);
	ada.reset();
	int cnt = 0, bef = -1;
	int idcnt = 0;
	bool ok = 0;
	FOR (i,0,SIZE(seg))
	{
		i3 &e = seg[i];
		while (!PQ.empty() && PQ.top().ff * -1 <= e.ff.ff)
		{
			ii now = take(PQ);
			now.ff *= -1;
			if (seg[now.ss].ff.ss + 1 == now.ff)
			{
				ada.set(now.ss, 0);
				--cnt;
				SET.erase(now.ss);
			}
		}
		ada.set(e.ss,1);
		++cnt;

		// tentukan ID
		if (cnt > m)
		{
			bef = *SET.begin();
			idseg[e.ss] = idseg[bef];
			seg[bef].ff.ss = e.ff.ss;
			PQ.push(mp(-e.ff.ss - 1, bef));
			ada.set(e.ss, 0);
			--cnt;
		}
		else
		{
			idseg[e.ss] = idcnt++;
			PQ.push(mp(-e.ff.ss - 1, e.ss));
			SET.insert(e.ss);
		}
		if (cnt == m) ok = 1;
	}

	if (!ok)
	{
		cout << "No solution\n";
		exit(0);
	}

	cout << idcnt << "\n";
	FOR (i,0,n) cout << idseg[i] + 1 << "\n";
	return 0;
}


#include <bits/stdc++.h>

#ifdef PEYEK
	#define debugln {printf("----OK----\n");}
	#define debug(...) {printf(__VA_ARGS__);}
	#define debugs(...) {printf(":::::--->> ");printf(__VA_ARGS__);}
	#define TIME() printf("%.3lf\n",clock()/(double)CLOCKS_PER_SEC)
#else
	#define debugln {}
	#define debug(...) {}
	#define debugs(...) {}
	#define TIME() {}
#endif

#define __INIT_CC__ ios::sync_with_stdio(false); \
	cin.tie(0);

#ifdef __WIN32__
	char getchar_unlocked() {return getchar();}
#endif

#define FOR(_i,_n,_m) for(int (_i)=(_n),_t=(_m);_i<(_t);++(_i))
#define FORN(_i,_n,_m) for(int (_i)=(_n),_t=(_m);_i<=(_t);++(_i))
#define FORD(_i,_n,_m) for(int (_i)=(_n),_t=(_m);_i>=(_t);--(_i))
#define FORLL(_i,_n,_m) for(long long (_i)=(_n),_t=(_m);_i<(_t);++(_i))
#define FORNLL(_i,_n,_m) for(long long (_i)=(_n),_t=(_m);(_i)<=(_t);++(_i))
#define FORDLL(_i,_n,_m) for(long long (_i)=(_n),_t=(_m);(_i)>=(_t);--(_i))
#define FOREACH(_i,_a) for (__typeof(_a.begin()) _i=_a.begin();_i!=_a.end();++_i)
#define RESET(_a,_value) memset(_a,_value,sizeof(_a))
#define pb push_back
#define ppb pop_back
#define pf push_front
#define ppf pop_front
#define ff first
#define ss second
#define mp make_pair
#define SIZE(_a) (int)_a.size()
#define VSORT(_a) sort(_a.begin(),_a.end())
#define SSORT(_a,_val) sort(_a,_a+(_val))
#define ALL(_a) _a.begin(),_a.end()
#define mt make_tuple
#define _get(_tuple,_i) get<_i>(_tuple)
#define eb emplace_back

using namespace std;

const int dr[]={ 1, 0,-1, 0, 1, 1,-1,-1};
const int dc[]={ 0, 1, 0,-1, 1,-1,-1, 1};
const double eps=1e-9;
typedef vector<int> vi;
typedef pair<int,int> ii;
typedef vector<ii> vii;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<ll,ll> pll;
typedef vector<pll> vpll;
typedef vector<ll> vll;
typedef pair<double,double> pdd;
typedef vector<pdd> vpdd;
const int INF=0x7FFFFFFF;
const ll INFLL=0x7FFFFFFFFFFFFFFFLL;
const double pi=acos(-1);

template <class T> T take(queue<T> &O) {T tmp=O.front();O.pop();return tmp;}
template <class T> T take(stack<T> &O) {T tmp=O.top();O.pop();return tmp;}
template <class T> T take(priority_queue<T> &O) {T tmp=O.top();O.pop();return tmp;}
template <class T> inline void getint(T &num)
{
	bool neg=0;
	num=0;
	char c;
	while ((c=getchar_unlocked()) && (!isdigit(c) && c!='-'));
	if (c=='-')
	{
		neg=1;
		c=getchar_unlocked();
	}
	do num=num*10+c-'0';
	while ((c=getchar_unlocked()) && isdigit(c));
	num*=(neg)?-1:1;
}

template <class T> inline bool inRange(T z, T a, T b){return a <= z && z <= b;}

void OPEN(string in="input.txt",string out="output.txt")
{
	freopen(in.c_str(),"r",stdin);
	freopen(out.c_str(),"w",stdout);
	return ;
}

//using sokokaleb's template v3.0

typedef pair<ii, int> i3;

int n, m, T;
vector<i3> seg;
int idseg[20005];
bitset<20005> ada;
set<int> SET;
priority_queue<ii> PQ;

int main(int argc, const char *argv[])
{
	getint(n);getint(m);getint(T);
	FOR (i,0,n)
	{
		int h,m,s;
		getint(h);getint(m);getint(s);
		s = h * 3600 + m * 60 + s;
		seg.pb(mp(mp(s, s + T - 1), i));
	}
	VSORT(seg);
	ada.reset();
	int cnt = 0, bef = -1;
	int idcnt = 0;
	bool ok = 0;
	FOR (i,0,SIZE(seg))
	{
		i3 &e = seg[i];
		while (!PQ.empty() && PQ.top().ff * -1 <= e.ff.ff)
		{
			ii now = take(PQ);
			now.ff *= -1;
			if (seg[now.ss].ff.ss == now.ff)
			{
				ada.set(now.ss, 0);
				--cnt;
				SET.erase(now.ss);
			}
		}
		ada.set(e.ss,1);
		++cnt;
		SET.insert(e.ss);

		// tentukan ID
		if (cnt == m) ok = 1;
		if (cnt > m)
		{
			bef = *SET.begin();
			idseg[e.ss] = idseg[bef];
			seg[bef].ff.ss = e.ff.ss;
			PQ.push(mp(-e.ff.ss, bef));
			ada.set(e.ss, 0);
			--cnt;
		}
		else
		{
			idseg[e.ss] = idcnt++;
			PQ.push(mp(-e.ff.ss, e.ss));
		}
	}

	if (!ok)
	{
		cout << "No solution\n";
		exit(0);
	}

	cout << idcnt << "\n";
	FOR (i,0,n) cout << idseg[i] + 1 << "\n";
	return 0;
}


#include <bits/stdc++.h>

#ifdef PEYEK
	#define debugln {printf("----OK----\n");}
	#define debug(...) {printf(__VA_ARGS__);}
	#define debugs(...) {printf(":::::--->> ");printf(__VA_ARGS__);}
	#define TIME() printf("%.3lf\n",clock()/(double)CLOCKS_PER_SEC)
#else
	#define debugln {}
	#define debug(...) {}
	#define debugs(...) {}
	#define TIME() {}
#endif

#define __INIT_CC__ ios::sync_with_stdio(false); \
	cin.tie(0);

#ifdef __WIN32__
	char getchar_unlocked() {return getchar();}
#endif

#define FOR(_i,_n,_m) for(int (_i)=(_n),_t=(_m);_i<(_t);++(_i))
#define FORN(_i,_n,_m) for(int (_i)=(_n),_t=(_m);_i<=(_t);++(_i))
#define FORD(_i,_n,_m) for(int (_i)=(_n),_t=(_m);_i>=(_t);--(_i))
#define FORLL(_i,_n,_m) for(long long (_i)=(_n),_t=(_m);_i<(_t);++(_i))
#define FORNLL(_i,_n,_m) for(long long (_i)=(_n),_t=(_m);(_i)<=(_t);++(_i))
#define FORDLL(_i,_n,_m) for(long long (_i)=(_n),_t=(_m);(_i)>=(_t);--(_i))
#define FOREACH(_i,_a) for (__typeof(_a.begin()) _i=_a.begin();_i!=_a.end();++_i)
#define RESET(_a,_value) memset(_a,_value,sizeof(_a))
#define pb push_back
#define ppb pop_back
#define pf push_front
#define ppf pop_front
#define ff first
#define ss second
#define mp make_pair
#define SIZE(_a) (int)_a.size()
#define VSORT(_a) sort(_a.begin(),_a.end())
#define SSORT(_a,_val) sort(_a,_a+(_val))
#define ALL(_a) _a.begin(),_a.end()
#define mt make_tuple
#define _get(_tuple,_i) get<_i>(_tuple)
#define eb emplace_back

using namespace std;

const int dr[]={ 1, 0,-1, 0, 1, 1,-1,-1};
const int dc[]={ 0, 1, 0,-1, 1,-1,-1, 1};
const double eps=1e-9;
typedef vector<int> vi;
typedef pair<int,int> ii;
typedef vector<ii> vii;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<ll,ll> pll;
typedef vector<pll> vpll;
typedef vector<ll> vll;
typedef pair<double,double> pdd;
typedef vector<pdd> vpdd;
const int INF=0x7FFFFFFF;
const ll INFLL=0x7FFFFFFFFFFFFFFFLL;
const double pi=acos(-1);

template <class T> T take(queue<T> &O) {T tmp=O.front();O.pop();return tmp;}
template <class T> T take(stack<T> &O) {T tmp=O.top();O.pop();return tmp;}
template <class T> T take(priority_queue<T> &O) {T tmp=O.top();O.pop();return tmp;}
template <class T> inline void getint(T &num)
{
	bool neg=0;
	num=0;
	char c;
	while ((c=getchar_unlocked()) && (!isdigit(c) && c!='-'));
	if (c=='-')
	{
		neg=1;
		c=getchar_unlocked();
	}
	do num=num*10+c-'0';
	while ((c=getchar_unlocked()) && isdigit(c));
	num*=(neg)?-1:1;
}

template <class T> inline bool inRange(T z, T a, T b){return a <= z && z <= b;}

void OPEN(string in="input.txt",string out="output.txt")
{
	freopen(in.c_str(),"r",stdin);
	freopen(out.c_str(),"w",stdout);
	return ;
}

//using sokokaleb's template v3.0

typedef pair<ii, int> i3;

int n, m, T;
vector<i3> seg;
int idseg[20005];
bitset<20005> ada;
set<int> SET;
priority_queue<ii> PQ;

int main(int argc, const char *argv[])
{
	getint(n);getint(m);getint(T);
	FOR (i,0,n)
	{
		int h,m,s;
		getint(h);getint(m);getint(s);
		s = h * 3600 + m * 60 + s;
		seg.pb(mp(mp(s, s + T - 1), i));
	}
	VSORT(seg);
	ada.reset();
	int cnt = 0, bef = -1;
	int idcnt = 0;
	bool ok = 0;
	FOR (i,0,SIZE(seg))
	{
		i3 &e = seg[i];
		while (!PQ.empty() && PQ.top().ff * -1 <= e.ff.ff)
		{
			ii now = take(PQ);
			now.ff *= -1;
			if (seg[now.ss].ff.ss + 1 == now.ff)
			{
				ada.set(now.ss, 0);
				--cnt;
				SET.erase(now.ss);
			}
		}
		ada.set(e.ss,1);
		++cnt;
		SET.insert(e.ss);

		// tentukan ID
		if (cnt == m) ok = 1;
		if (cnt > m)
		{
			bef = *SET.begin();
			idseg[e.ss] = idseg[bef];
			seg[bef].ff.ss = e.ff.ss;
			PQ.push(mp(-e.ff.ss - 1, bef));
			ada.set(e.ss, 0);
			--cnt;
		}
		else
		{
			idseg[e.ss] = idcnt++;
			PQ.push(mp(-e.ff.ss - 1, e.ss));
		}
	}

	if (!ok)
	{
		cout << "No solution\n";
		exit(0);
	}

	cout << idcnt << "\n";
	FOR (i,0,n) cout << idseg[i] + 1 << "\n";
	return 0;
}


#include <bits/stdc++.h>

#ifdef PEYEK
	#define debugln {printf("----OK----\n");}
	#define debug(...) {printf(__VA_ARGS__);}
	#define debugs(...) {printf(":::::--->> ");printf(__VA_ARGS__);}
	#define TIME() printf("%.3lf\n",clock()/(double)CLOCKS_PER_SEC)
#else
	#define debugln {}
	#define debug(...) {}
	#define debugs(...) {}
	#define TIME() {}
#endif

#define __INIT_CC__ ios::sync_with_stdio(false); \
	cin.tie(0);

#ifdef __WIN32__
	char getchar_unlocked() {return getchar();}
#endif

#define FOR(_i,_n,_m) for(int (_i)=(_n),_t=(_m);_i<(_t);++(_i))
#define FORN(_i,_n,_m) for(int (_i)=(_n),_t=(_m);_i<=(_t);++(_i))
#define FORD(_i,_n,_m) for(int (_i)=(_n),_t=(_m);_i>=(_t);--(_i))
#define FORLL(_i,_n,_m) for(long long (_i)=(_n),_t=(_m);_i<(_t);++(_i))
#define FORNLL(_i,_n,_m) for(long long (_i)=(_n),_t=(_m);(_i)<=(_t);++(_i))
#define FORDLL(_i,_n,_m) for(long long (_i)=(_n),_t=(_m);(_i)>=(_t);--(_i))
#define FOREACH(_i,_a) for (__typeof(_a.begin()) _i=_a.begin();_i!=_a.end();++_i)
#define RESET(_a,_value) memset(_a,_value,sizeof(_a))
#define pb push_back
#define ppb pop_back
#define pf push_front
#define ppf pop_front
#define ff first
#define ss second
#define mp make_pair
#define SIZE(_a) (int)_a.size()
#define VSORT(_a) sort(_a.begin(),_a.end())
#define SSORT(_a,_val) sort(_a,_a+(_val))
#define ALL(_a) _a.begin(),_a.end()
#define mt make_tuple
#define _get(_tuple,_i) get<_i>(_tuple)
#define eb emplace_back

using namespace std;

const int dr[]={ 1, 0,-1, 0, 1, 1,-1,-1};
const int dc[]={ 0, 1, 0,-1, 1,-1,-1, 1};
const double eps=1e-9;
typedef vector<int> vi;
typedef pair<int,int> ii;
typedef vector<ii> vii;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<ll,ll> pll;
typedef vector<pll> vpll;
typedef vector<ll> vll;
typedef pair<double,double> pdd;
typedef vector<pdd> vpdd;
const int INF=0x7FFFFFFF;
const ll INFLL=0x7FFFFFFFFFFFFFFFLL;
const double pi=acos(-1);

template <class T> T take(queue<T> &O) {T tmp=O.front();O.pop();return tmp;}
template <class T> T take(stack<T> &O) {T tmp=O.top();O.pop();return tmp;}
template <class T> T take(priority_queue<T> &O) {T tmp=O.top();O.pop();return tmp;}
template <class T> inline void getint(T &num)
{
	bool neg=0;
	num=0;
	char c;
	while ((c=getchar_unlocked()) && (!isdigit(c) && c!='-'));
	if (c=='-')
	{
		neg=1;
		c=getchar_unlocked();
	}
	do num=num*10+c-'0';
	while ((c=getchar_unlocked()) && isdigit(c));
	num*=(neg)?-1:1;
}

template <class T> inline bool inRange(T z, T a, T b){return a <= z && z <= b;}

void OPEN(string in="input.txt",string out="output.txt")
{
	freopen(in.c_str(),"r",stdin);
	freopen(out.c_str(),"w",stdout);
	return ;
}

//using sokokaleb's template v3.0

typedef pair<ii, int> i3;

int n, m, T;
vector<i3> seg;
int idseg[20005];
bitset<20005> ada;
set<ii> SET;
set<ii> SETQ;

int main(int argc, const char *argv[])
{
	getint(n);getint(m);getint(T);
	FOR (i,0,n)
	{
		int h,m,s;
		getint(h);getint(m);getint(s);
		s = h * 3600 + m * 60 + s;
		seg.pb(mp(mp(s, s + T - 1), i));
	}
	VSORT(seg);
	ada.reset();
	int cnt = 0, bef = -1;
	int idcnt = 0;
	bool ok = 0;
	FOR (i,0,SIZE(seg))
	{
		i3 &e = seg[i];
		while (!SETQ.empty() && (*SETQ.begin()).ff <= e.ff.ff)
		{
			ii now = *SETQ.begin();
			SETQ.erase(SETQ.begin());
			ada.set(now.ss, 0);
			--cnt;
			SET.erase(mp(seg[now.ss].ff.ff, now.ss));
		}
		ada.set(e.ss,1);
		++cnt;

		// tentukan ID
		if (cnt > m)
		{
			idseg[e.ss] = idseg[bef];
			SETQ.erase(mp(seg[bef].ff.ss + 1, seg[bef].ss));
			seg[bef].ff.ss = e.ff.ss;
			SETQ.insert(mp(e.ff.ss + 1, seg[bef].ss));
			ada.set(e.ss, 0);
			--cnt;
		}
		else
		{
			idseg[e.ss] = idcnt++;
			SETQ.insert(mp(e.ff.ss + 1, e.ss));
			bef = i;
		}
		if (cnt == m) ok = 1;
	}

	if (!ok)
	{
		cout << "No solution\n";
		exit(0);
	}

	cout << idcnt << "\n";
	FOR (i,0,n) cout << idseg[i] + 1 << "\n";
	return 0;
}


using System;
using System.Linq;
using System.Collections.Generic;
using Debug = System.Diagnostics.Debug;
using StringBuilder = System.Text.StringBuilder;
//using System.Numerics;
namespace Program
{
    public class Solver
    {
        public void Solve()
        {
            var n = sc.Integer();
            var m = sc.Integer();
            var G = Enumerate(n, x => new List<Trinity<int, int, int>>());
            var a = new int[2];
            var edge = new Trinity<int, int, int>[m];
            for (int i = 0; i < m; i++)
            {
                var s = sc.Integer() - 1;
                var t = sc.Integer() - 1;
                var k = sc.Integer();
                edge[i] = Trinity.Create(s + 1, t + 1, k);
                a[k]++;
                G[s].Add(Trinity.Create(t, k, i));
                G[t].Add(Trinity.Create(s, k, i));
            }
            var dist = new int[n];
            var minCost = new int[n];
            var prev = new int[n];
            var id = new int[n];
            for (int i = 0; i < n; i++)
            {
                dist[i] = int.MaxValue;
                minCost[i] = int.MaxValue;
                prev[i] = -1;
                id[i] = -1;
            }
            dist[0] = 0;
            minCost[0] = a[1];
            var pq = new MergeablePriorityQueue<Trinity<int, int, int>>();
            pq.Enqueue(Trinity.Create(0, a[1], 0));
            while (pq.Any())
            {
                var p = pq.Dequeue();
                var d = p.I;
                var cost = p.J;
                var pos = p.K;
                if (dist[pos] < d) continue;
                else if (dist[pos] == d && minCost[pos] < cost) continue;
                foreach (var next in G[pos])
                {
                    var to = next.I;
                    var e = d + 1;
                    var v = cost;
                    if (next.J == 0) v++;
                    else v--;
                    if (v > m || v < 0) continue;
                    if (dist[to] > e || (dist[to] == e && minCost[to] > v))
                    {
                        pq.Enqueue(Trinity.Create(e, v, to));
                        dist[to] = e;
                        minCost[to] = v;
                        prev[to] = pos;
                        id[to] = next.K;
                    }
                }
            }
            var last = n - 1;
            var used = new bool[m];
            while (prev[last] >= 0)
            {
                used[id[last]] = true;
                last = prev[last];
            }
            IO.Printer.Out.WriteLine(minCost[n - 1]);
            for (int i = 0; i < m; i++)
            {
                if (used[i] && edge[i].K == 1) continue;
                else if (!used[i] && edge[i].K == 0) continue;
                IO.Printer.Out.WriteLine("{0} {1} {2}", edge[i].I, edge[i].J, edge[i].K ^ 1);
            }
        }

        internal IO.StreamScanner sc = new IO.StreamScanner(Console.OpenStandardInput());
        static T[] Enumerate<T>(int n, Func<T> f) { var a = new T[n]; for (int i = 0; i < n; ++i) a[i] = f(); return a; }
        static T[] Enumerate<T>(int n, Func<int, T> f) { var a = new T[n]; for (int i = 0; i < n; ++i) a[i] = f(i); return a; }

    }

}

#region Ex
namespace Program.IO
{
    using System.IO;
    using System.Linq;
    public class Printer : StreamWriter
    {
        static Printer()
        {
            Out = new Printer(Console.OpenStandardOutput()) { AutoFlush = false };
        }
        public static Printer Out { get; set; }
        public override IFormatProvider FormatProvider { get { return System.Globalization.CultureInfo.InvariantCulture; } }
        public Printer(System.IO.Stream stream) : base(stream, new System.Text.UTF8Encoding(false, true)) { }
        public void Write<T>(string format, IEnumerable<T> source) { base.Write(format, source.OfType<object>().ToArray()); }
        public void WriteLine<T>(string format, IEnumerable<T> source) { base.WriteLine(format, source.OfType<object>().ToArray()); }
    }
    public class StreamScanner
    {
        public StreamScanner(Stream stream) { str = stream; }
        private readonly Stream str;
        private readonly byte[] buf = new byte[1024];
        private int len, ptr;
        public bool isEof = false;
        public bool IsEndOfStream { get { return isEof; } }
        private byte read()
        {
            if (isEof) return 0;
            if (ptr >= len) { ptr = 0; if ((len = str.Read(buf, 0, 1024)) <= 0) { isEof = true; return 0; } }
            return buf[ptr++];
        }
        public char Char() { byte b = 0; do b = read(); while (b < 33 || 126 < b); return (char)b; }
        public char[] Char(int n) { var a = new char[n]; for (int i = 0; i < n; i++) a[i] = Char(); return a; }
        public string Scan()
        {
            var sb = new StringBuilder();
            for (var b = Char(); b >= 33 && b <= 126; b = (char)read())
                sb.Append(b);
            return sb.ToString();
        }
        public long Long()
        {
            if (isEof) return long.MinValue;
            long ret = 0; byte b = 0; var ng = false;
            do b = read();
            while (b != '-' && (b < '0' || '9' < b));
            if (b == '-') { ng = true; b = read(); }
            for (; true; b = read())
            {
                if (b < '0' || '9' < b)
                    return ng ? -ret : ret;
                else ret = ret * 10 + b - '0';
            }
        }
        public int Integer() { return (isEof) ? int.MinValue : (int)Long(); }
        public double Double() { return double.Parse(Scan(), System.Globalization.CultureInfo.InvariantCulture); }
        private T[] enumerate<T>(int n, Func<T> f)
        {
            var a = new T[n];
            for (int i = 0; i < n; ++i) a[i] = f();
            return a;
        }

        public string[] Scan(int n) { return enumerate(n, Scan); }
        public double[] Double(int n) { return enumerate(n, Double); }
        public int[] Integer(int n) { return enumerate(n, Integer); }
        public long[] Long(int n) { return enumerate(n, Long); }
        public void Flush() { str.Flush(); }

    }
}
static class Ex
{
    static public string AsString(this IEnumerable<char> ie) { return new string(System.Linq.Enumerable.ToArray(ie)); }
    static public string AsJoinedString<T>(this IEnumerable<T> ie, string st = " ") { return string.Join(st, ie); }
    static public void Main()
    {
        var solver = new Program.Solver();
        solver.Solve();
        Program.IO.Printer.Out.Flush();
    }
}
#endregion
#region PriorityQueue and PairingHeap
public class MergeablePriorityQueue<T>
{
    PairingHeap<T> top;
    Comparison<T> compare;
    int size;
    public int Count { get { return size; } }
    public MergeablePriorityQueue() : this(Comparer<T>.Default) { }
    public MergeablePriorityQueue(Comparison<T> comparison) { compare = comparison; }
    public MergeablePriorityQueue(IComparer<T> comparer) { compare = comparer.Compare; }
    public void Enqueue(T item)
    {
        var heap = new PairingHeap<T>(item);
        top = PairingHeap<T>.Merge(top, heap, compare);
        size++;
    }
    public T Dequeue()
    {
        var ret = top.Key;
        size--;
        top = PairingHeap<T>.Pop(top, compare);
        return ret;
    }
    public bool Any() { return size > 0; }
    public T Peek() { return top.Key; }
}

#region PairingHeap
public class PairingHeap<T>
{
    public PairingHeap(T k) { key = k; }
    private readonly T key;
    public T Key { get { return key; } }
    private PairingHeap<T> head;
    private PairingHeap<T> next;
    static public PairingHeap<T> Pop(PairingHeap<T> s, Comparison<T> compare)
    {
        return MergeLst(s.head, compare);
    }
    static public PairingHeap<T> Merge(PairingHeap<T> l, PairingHeap<T> r, Comparison<T> compare)
    {
        if (l == null || r == null) return l == null ? r : l;
        if (compare(l.key, r.key) > 0) Swap(ref l, ref r);
        r.next = l.head;
        l.head = r;
        return l;
    }
    static public PairingHeap<T> MergeLst(PairingHeap<T> s, Comparison<T> compare)
    {
        var n = new PairingHeap<T>(default(T));
        while (s != null)
        {
            PairingHeap<T> a = s, b = null;
            s = s.next; a.next = null;
            if (s != null) { b = s; s = s.next; b.next = null; }
            a = Merge(a, b, compare); a.next = n.next;
            n.next = a;
        }
        while (n.next != null)
        {
            var j = n.next;
            n.next = n.next.next;
            s = Merge(j, s, compare);
        }
        return s;
    }
    static void Swap(ref PairingHeap<T> l, ref PairingHeap<T> r) { var t = l; l = r; r = t; }
}
#endregion
#endregion

#region Trinity<ST,FT,TT>
static public class Trinity
{
    static public Trinity<FT, ST, TT> Create<FT, ST, TT>(FT f, ST s, TT t)
        where FT : IComparable<FT>
        where ST : IComparable<ST>
        where TT : IComparable<TT>
    { return new Trinity<FT, ST, TT>(f, s, t); }
}
public struct Trinity<FT, ST, TT> : IComparable<Trinity<FT, ST, TT>>
    where FT : IComparable<FT>
    where ST : IComparable<ST>
    where TT : IComparable<TT>
{
    public FT I;
    public ST J;
    public TT K;
    public Trinity(FT i, ST j, TT k) : this() { I = i; J = j; K = k; }
    public int CompareTo(Trinity<FT, ST, TT> other)
    {
        var cmp = I.CompareTo(other.I);
        if (cmp != 0) return cmp;
        return cmp = J.CompareTo(other.J);
    }
    public override string ToString() { return string.Format("{0} {1} {2}", I, J, K); }
}
#endregion