Submission #2869226


Source Code Expand

import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.Set;
import java.util.TreeSet;

public class Main {
	private static void solve() {
		int n = nei();
		int m = nei();
		int k = nei();
		char[] cs = ncs(n);
		int[][] abs = nis2(m, 2);

		boolean[] visited = new boolean[n];
		int[] ret = new int[n];
		int numRet = n;
		int[] stack = new int[n];
		int stackCount = 0;
		while (true) {
			for (int i = 0; i < n; i++) {
				if (!visited[i]) {
					stackCount = 1;
					stack[0] = i;
					break;
				}
			}
			if (stackCount == 0)
				break;
			while (stackCount > 0) {
				int i = stack[--stackCount];
				visited[i] = true;
				int next = -1;
				for (int j = 0; j < m; j++) { // n <= 300, m <= 1000 so O(nm) is ok
					int a = abs[j][0] - 1;
					int b = abs[j][1] - 1;
					if (a == i && !visited[b]) {
						next = b;
						break;
					}
				}
				if (next == -1) {
					ret[--numRet] = i;
				} else {
					stack[stackCount++] = i;
					stack[stackCount++] = next;
				}
			}
		}
		for (int i = 0; i < n; i++) {
			visited[i] = false;
		}
		int[] dagIdx = new int[n];
		int dagN = 0;
		while (true) {
			for (int i = 0; i < n; i++) {
				if (!visited[ret[i]]) {
					stackCount = 1;
					stack[0] = ret[i];
					break;
				}
			}
			if (stackCount == 0)
				break;
			while (stackCount > 0) {
				int i = stack[--stackCount];
				visited[i] = true;
				int next = -1;
				for (int j = 0; j < m; j++) { // n <= 300, m <= 1000 so O(nm) is ok
					int b = abs[j][0] - 1;
					int a = abs[j][1] - 1;
					if (a == i && !visited[b]) {
						next = b;
						break;
					}
				}
				if (next == -1) {
					dagIdx[i] = dagN;
				} else {
					stack[stackCount++] = i;
					stack[stackCount++] = next;
				}
			}
			dagN++;
		}
		ArrayList<ArrayList<Character>> chars = new ArrayList<ArrayList<Character>>();
		for (int i = 0; i < dagN; i++) {
			chars.add(new ArrayList<Character>());
		}
		for (int i = 0; i < n; i++) {
			chars.get(dagIdx[i]).add(cs[i]);
		}
		for (int i = 0; i < dagN; i++) {
			Collections.sort(chars.get(i));
		}
		int[][] dag = new int[dagN][];
		int[][] dagR = new int[dagN][];
		boolean[][] dagA = new boolean[dagN][dagN];
		int[] numesR = new int[dagN];
		int[] numes = new int[dagN];
		for (int i = 0; i < m; i++) {
			int da = dagIdx[abs[i][0] - 1]; // reverse edges
			int db = dagIdx[abs[i][1] - 1];
			if (da != db)
				dagA[da][db] = true;
		}
		for (int i = 0; i < dagN; i++) {
			for (int j = 0; j < dagN; j++) {
				if (dagA[i][j]) {
					numes[i]++;
				}
				if (dagA[j][i]) {
					numesR[i]++;
				}
			}
			dag[i] = new int[numes[i]];
			dagR[i] = new int[numesR[i]];
			numes[i] = 0;
			numesR[i] = 0;
			for (int j = 0; j < dagN; j++) {
				if (dagA[i][j])
					dag[i][numes[i]++] = j;
				if (dagA[j][i])
					dagR[i][numesR[i]++] = j;
			}
		}

		String[][] dp = new String[dagN][500]; // dagN'th vertex から始めて k 文字集める辞書順最小
		int[] dpNum = new int[500];
		String[] po = new String[500];
		for (int i = dagN-1; i >=0; i--) {
			String s = "";
			po[0] = "";
			dp[i][0] = "";
			int num = 0;
			for (char c : chars.get(i)) {
				s += c;
				po[s.length()] = s;
				dp[i][s.length()] = s;
				num++;
			}
//			System.out.println("index=" + i + ", num=" + num);
			int maxnum = num;
			for (int j = 0; j < numes[i]; j++) {
				int to = dag[i][j];
				int num2 = dpNum[to];
//				System.out.println("to=" + to + " num2=" + num2);
				maxnum = max(maxnum, num + num2);
				for (int i1 = 0; i1 <= num; i1++) {
					for (int i2 = 0; i2 <= num2; i2++) {
						String aaa = po[i1] + dp[to][i2];
						dp[i][i1 + i2] = strmin(dp[i][i1 + i2], aaa);
					}
				}
			}
//			System.out.println("index=" + i + ", numdp=" + maxnum);
			dpNum[i] = maxnum;
			for (int j = 0; j < numesR[i]; j++) {
				int to = dagR[i][j];
				if (!visited[to]) {
					visited[to] = true;
				}
			}
		}
		String min = null;
		for (int i = 0; i < dagN; i++) {
			min = strmin(min, dp[i][k]);
		}
		out(min == null ? -1 : min);
	}

	static String strmin(String a, String b) {
		if (a == null)
			return b;
		if (b == null)
			return a;
		return a.compareTo(b) < 0 ? a : b;
	}

	void dfs(int i, boolean[] visited, int[] ret, int numRet) {

	}

	// returns (x, y, d) s.t. ax + by = d
	static long[] exgcd(long a, long b) {
		int sa = a < 0 ? -1 : 1;
		int sb = b < 0 ? -1 : 1;
		a *= sa;
		b *= sb;
		long x = 1;
		long y = 0;
		long z = 0;
		long w = 1;
		while (b > 0) {
			long q = a / b;
			long t = z;
			z = x - q * z;
			x = t;
			t = w;
			w = y - q * w;
			y = t;
			t = b;
			b = a - q * b;
			a = t;
		}
		return new long[] { x * sa, y * sb, a };
	}

	static int[] lis(int[] s) {
		int n = s.length;
		int[] dp = new int[n];
		int[] ids = new int[n];
		int[] pids = new int[n];
		dp[0] = s[0];
		int len = 1;
		int lidx = 0;
		for (int i = 1; i < n; i++) {
			int idx = bs(s[i], dp, 0, len);
			dp[idx] = s[i];
			ids[idx] = i;
			if (idx == len) {
				lidx = i;
				len++;
			}
			if (idx > 0)
				pids[i] = ids[idx - 1];
		}
		int[] lis = new int[len];
		lis[len - 1] = s[lidx];
		for (int i = len - 1; i >= 0; i--) {
			lis[i] = s[lidx];
			lidx = pids[lidx];
		}
		return lis;
	}

	static int bs(int a, int[] as, int from, int num) {
		int min = from;
		int max = from + num - 1;
		while (min < max) {
			int mid = min + max >> 1;
			if (as[mid] < a)
				min = mid + 1;
			else if (as[mid] > a)
				max = mid;
			else
				return mid;
		}
		return as[min] < a ? min + 1 : min;
	}

	static int gcd(int x, int y) {
		x = (x ^ x >> 31) - (x >> 31);
		y = (y ^ y >> 31) - (y >> 31);
		if (x < y) {
			x ^= y;
			y ^= x;
			x ^= y;
		}
		int z = x % y;
		if (z == 0)
			return y;
		return gcd(y, z);
	}

	static long gcd(long x, long y) {
		x = (x ^ x >> 63) - (x >> 63);
		y = (y ^ y >> 63) - (y >> 63);
		if (x < y) {
			x ^= y;
			y ^= x;
			x ^= y;
		}
		long z = x % y;
		if (z == 0)
			return y;
		return gcd(y, z);
	}

	static long modinv(long a, long mod) {
		return modpow(a, mod - 2, mod);
	}

	static long modpow(long a, long b, long mod) {
		if (b == 0)
			return 1;
		if ((b & 1) == 0) {
			long sqrt = modpow(a, b >> 1, mod);
			return sqrt * sqrt % mod;
		}
		return a * modpow(a, b - 1, mod) % mod;
	}

	static long fact(long n) {
		if (n <= 1)
			return 1;
		long res = 2;
		for (long i = 3; i <= n; i++) {
			res *= i;
		}
		return res;
	}

	static long modfact(long n, long mod) {
		if (n <= 1)
			return 1 % mod;
		long res = 2;
		for (long i = 3; i <= n; i++) {
			res *= i;
			res %= mod;
		}
		return res % mod;
	}

	// returns facts([0]) and invfacts([1])
	static long[][] enumfacts(int n, long mod) {
		int num = n + 10;
		long[][] res = new long[2][num];
		long[] facts = res[0];
		long[] invfacts = res[1];
		for (int i = 0; i < num; i++) {
			if (i <= 1) {
				facts[i] = 1;
				invfacts[i] = 1;
			} else {
				facts[i] = facts[i - 1] * i % mod;
				invfacts[i] = modinv(facts[i], mod);
			}
		}
		return res;
	}

	static long modcomb(long n, long m, long mod) {
		if (m > n)
			return 0;
		if (m > n - m) {
			m = n - m;
		}
		long numer = 1;
		for (int i = 0; i < m; i++) {
			numer = numer * (n - i) % mod;
		}
		long denom = modfact(m, mod);
		return numer * denom % mod;
	}

	static long modcomb(int n, int m, long[] facts, long[] invfacts, long mod) {
		if (m > n)
			return 0;
		long numer = facts[n];
		long denom = invfacts[m] * invfacts[n - m] % mod;
		return numer * denom % mod;
	}

	// res[i][0]: prime factor, res[i][1]: exponent
	static int[][] factorize(int n) {
		int[][] pfs = new int[32][2];
		int num = 0;
		for (int i = 2; i * i <= n; i++) {
			int count = 0;
			while (n % i == 0) {
				n /= i;
				count++;
			}
			if (count > 0) {
				pfs[num][0] = i;
				pfs[num][1] = count;
				num++;
			}
		}
		if (n > 1) {
			pfs[num][0] = n;
			pfs[num][1] = 1;
			num++;
		}
		int[][] res = new int[num][2];
		for (int i = 0; i < num; i++) {
			res[i][0] = pfs[i][0];
			res[i][1] = pfs[i][1];
		}
		return res;
	}

	static long lcm(long x, long y) {
		x = (x ^ x >> 63) - (x >> 63);
		y = (y ^ y >> 63) - (y >> 63);
		return x / gcd(x, y) * y;
	}

	static int abs(int x) {
		return x < 0 ? -x : x;
	}

	static long abs(long x) {
		return x < 0 ? -x : x;
	}

	static int min(int a, int b) {
		return a < b ? a : b;
	}

	static long min(long a, long b) {
		return a < b ? a : b;
	}

	static int max(int a, int b) {
		return a > b ? a : b;
	}

	static long max(long a, long b) {
		return a > b ? a : b;
	}

	static int clamp(int a, int min, int max) {
		return a < min ? min : a > max ? max : a;
	}

	static long clamp(long a, long min, long max) {
		return a < min ? min : a > max ? max : a;
	}

	static double clamp(double a, double min, double max) {
		return a < min ? min : a > max ? max : a;
	}

	static void out(String val) {
		IO.out(val);
	}

	static void out(Object val) {
		IO.out(String.valueOf(val));
	}

	static void out(int val) {
		IO.out(String.valueOf(val));
	}

	static void out(long val) {
		IO.out(String.valueOf(val));
	}

	static void out(char val) {
		IO.out(String.valueOf(val));
	}

	static void out(double val) {
		IO.out(Double.isFinite(val) ? BigDecimal.valueOf(val).toPlainString() : String.valueOf(val));
	}

	static void out(boolean val) {
		IO.out(val ? "true" : "false");
	}

	static void kil(String val) {
		IO.out(val);
		IO.flush();
		System.exit(0);
	}

	static void kil(Object val) {
		IO.out(String.valueOf(val));
		IO.flush();
		System.exit(0);
	}

	static void kil(int val) {
		IO.out(String.valueOf(val));
		IO.flush();
		System.exit(0);
	}

	static void kil(long val) {
		IO.out(String.valueOf(val));
		IO.flush();
		System.exit(0);
	}

	static void kil(char val) {
		IO.out(String.valueOf(val));
		IO.flush();
		System.exit(0);
	}

	static void kil(double val) {
		IO.out(Double.isFinite(val) ? BigDecimal.valueOf(val).toPlainString() : String.valueOf(val));
		IO.flush();
		System.exit(0);
	}

	static void kil(boolean val) {
		IO.out(val ? "true" : "false");
		IO.flush();
		System.exit(0);
	}

	static String nes() {
		return IO.next();
	}

	static int nei() {
		return IO.nextInt();
	}

	static long nel() {
		return IO.nextLong();
	}

	static double ned() {
		return IO.nextDouble();
	}

	static char nec() {
		return IO.nextChar();
	}

	static String[] nss(int n) {
		String[] as = new String[n];
		for (int i = 0; i < n; i++) {
			as[i] = IO.next();
		}
		return as;
	}

	static int[] nis(int n) {
		int[] as = new int[n];
		for (int i = 0; i < n; i++) {
			as[i] = IO.nextInt();
		}
		return as;
	}

	static long[] nls(int n) {
		long[] as = new long[n];
		for (int i = 0; i < n; i++) {
			as[i] = IO.nextLong();
		}
		return as;
	}

	static double[] nds(int n) {
		double[] as = new double[n];
		for (int i = 0; i < n; i++) {
			as[i] = IO.nextDouble();
		}
		return as;
	}

	static char[] ncs(int n) {
		char[] as = new char[n];
		for (int i = 0; i < n; i++) {
			as[i] = IO.nextChar();
		}
		return as;
	}

	static String[][] nss2(int n, int m) {
		String[][] as = new String[n][m];
		for (int i = 0; i < n; i++) {
			for (int j = 0; j < m; j++) {
				as[i][j] = IO.next();
			}
		}
		return as;
	}

	static int[][] nis2(int n, int m) {
		int[][] as = new int[n][m];
		for (int i = 0; i < n; i++) {
			for (int j = 0; j < m; j++) {
				as[i][j] = IO.nextInt();
			}
		}
		return as;
	}

	static long[][] nls2(int n, int m) {
		long[][] as = new long[n][m];
		for (int i = 0; i < n; i++) {
			for (int j = 0; j < m; j++) {
				as[i][j] = IO.nextLong();
			}
		}
		return as;
	}

	static double[][] nds2(int n, int m) {
		double[][] as = new double[n][m];
		for (int i = 0; i < n; i++) {
			for (int j = 0; j < m; j++) {
				as[i][j] = IO.nextDouble();
			}
		}
		return as;
	}

	static char[][] ncs2(int n, int m) {
		char[][] as = new char[n][m];
		for (int i = 0; i < n; i++) {
			for (int j = 0; j < m; j++) {
				as[i][j] = IO.nextChar();
			}
		}
		return as;
	}

	static int parseInt(String val) {
		return Integer.parseInt(val);
	}

	static int parseInt(char val) {
		return Integer.parseInt(String.valueOf(val));
	}

	static long parseLong(String val) {
		return Long.parseLong(val);
	}

	public static void main(String[] args) {
		try {
			solve();
			IO.flush();
		} catch (NumberFormatException e) {
			e.printStackTrace();
		}
	}
}

final class IO {
	private static final InputStream in = System.in;
	private static final PrintWriter out = new PrintWriter(System.out, false);
	private static final byte[] buffer = new byte[1024];
	private static int ptr = 0;
	private static int len = 0;

	private static boolean hasNextByte() {
		if (ptr < len)
			return true;
		ptr = 0;
		try {
			len = in.read(buffer);
		} catch (IOException e) {
			e.printStackTrace();
		}
		return len > 0;
	}

	private static int readByte() {
		if (hasNextByte())
			return buffer[ptr++];
		else
			return -1;
	}

	static boolean hasNext() {
		byte c;
		while (hasNextByte() && ((c = buffer[ptr]) < '!' || c > '~'))
			ptr++;
		return hasNextByte();
	}

	static String next() {
		if (!hasNext())
			throw new NoSuchElementException();
		StringBuilder sb = new StringBuilder();
		int b = readByte();
		while (b >= '!' && b <= '~') {
			sb.append((char) b);
			b = readByte();
		}
		return sb.toString();
	}

	static char nextChar() {
		if (!hasNext())
			throw new NoSuchElementException();
		return (char) readByte();
	}

	static long nextLong() {
		if (!hasNext())
			throw new NoSuchElementException();
		long n = 0;
		int sign = 1;
		int b = readByte();
		if (b == '-') {
			sign = -1;
			b = readByte();
		}
		if (b < '0' || '9' < b)
			throw new NumberFormatException();
		while (true) {
			if ('0' <= b && b <= '9')
				n = n * 10 + b - '0';
			else if (b == -1 || b < '!' || b > '~')
				return n * sign;
			else
				throw new NumberFormatException();
			b = readByte();
		}
	}

	static int nextInt() {
		if (!hasNext())
			throw new NoSuchElementException();
		int n = 0;
		int sign = 1;
		int b = readByte();
		if (b == '-') {
			sign = -1;
			b = readByte();
		}
		if (b < '0' || '9' < b)
			throw new NumberFormatException();
		while (true) {
			if ('0' <= b && b <= '9')
				n = n * 10 + b - '0';
			else if (b == -1 || b < '!' || b > '~')
				return n * sign;
			else
				throw new NumberFormatException();
			b = readByte();
		}
	}

	static double nextDouble() {
		return Double.parseDouble(next());
	}

	static void out(String val) {
		out.println(val);
	}

	static void flush() {
		out.flush();
	}
}

Submission Info

Submission Time
Task C - 有向グラフ
User saharan
Language Java8 (OpenJDK 1.8.0)
Score 100
Code Size 15310 Byte
Status AC
Exec Time 174 ms
Memory 50644 KB

Judge Result

Set Name Sample All
Score / Max Score 0 / 0 100 / 100
Status
AC × 4
AC × 32
Set Name Test Cases
Sample subtask0_sample_01.txt, subtask0_sample_02.txt, subtask0_sample_03.txt, subtask0_sample_04.txt
All subtask0_sample_01.txt, subtask0_sample_02.txt, subtask0_sample_03.txt, subtask0_sample_04.txt, subtask1_manual01.txt, subtask1_manual02.txt, subtask1_manual03.txt, subtask1_manual04.txt, subtask1_manual05.txt, subtask1_manual06.txt, subtask1_manual07.txt, subtask1_manual08.txt, subtask1_random01.txt, subtask1_random02.txt, subtask1_random03.txt, subtask1_random04.txt, subtask1_random05.txt, subtask1_special01.txt, subtask1_special02.txt, subtask1_special03.txt, subtask1_special04.txt, subtask1_special05.txt, subtask1_special06.txt, subtask1_special07.txt, subtask1_special08.txt, subtask1_special09.txt, subtask1_special10.txt, subtask1_special11.txt, subtask1_special12.txt, subtask1_special13.txt, subtask1_special14.txt, subtask1_special15.txt
Case Name Status Exec Time Memory
subtask0_sample_01.txt AC 71 ms 19284 KB
subtask0_sample_02.txt AC 70 ms 19284 KB
subtask0_sample_03.txt AC 70 ms 23124 KB
subtask0_sample_04.txt AC 70 ms 18132 KB
subtask1_manual01.txt AC 71 ms 19284 KB
subtask1_manual02.txt AC 71 ms 18004 KB
subtask1_manual03.txt AC 72 ms 18260 KB
subtask1_manual04.txt AC 70 ms 19156 KB
subtask1_manual05.txt AC 72 ms 18772 KB
subtask1_manual06.txt AC 72 ms 22740 KB
subtask1_manual07.txt AC 72 ms 20692 KB
subtask1_manual08.txt AC 71 ms 18388 KB
subtask1_random01.txt AC 128 ms 38600 KB
subtask1_random02.txt AC 127 ms 33676 KB
subtask1_random03.txt AC 136 ms 41848 KB
subtask1_random04.txt AC 125 ms 36236 KB
subtask1_random05.txt AC 120 ms 30164 KB
subtask1_special01.txt AC 87 ms 20436 KB
subtask1_special02.txt AC 167 ms 48596 KB
subtask1_special03.txt AC 168 ms 48852 KB
subtask1_special04.txt AC 162 ms 50644 KB
subtask1_special05.txt AC 162 ms 50516 KB
subtask1_special06.txt AC 157 ms 44884 KB
subtask1_special07.txt AC 145 ms 43092 KB
subtask1_special08.txt AC 147 ms 44244 KB
subtask1_special09.txt AC 148 ms 44244 KB
subtask1_special10.txt AC 154 ms 45908 KB
subtask1_special11.txt AC 149 ms 41172 KB
subtask1_special12.txt AC 146 ms 40148 KB
subtask1_special13.txt AC 149 ms 38996 KB
subtask1_special14.txt AC 98 ms 21460 KB
subtask1_special15.txt AC 174 ms 50644 KB