結果

問題 No.1069 電柱 / Pole (Hard)
ユーザー CuriousFairy315CuriousFairy315
提出日時 2020-05-29 23:09:25
言語 Java21
(openjdk 21)
結果
WA  
実行時間 -
コード長 11,199 bytes
コンパイル時間 3,038 ms
コンパイル使用メモリ 96,076 KB
実行使用メモリ 58,588 KB
最終ジャッジ日時 2024-11-06 12:12:14
合計ジャッジ時間 13,667 ms
ジャッジサーバーID
(参考情報)
judge5 / judge2
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 72 ms
51,092 KB
testcase_01 AC 75 ms
51,068 KB
testcase_02 AC 71 ms
51,152 KB
testcase_03 AC 71 ms
50,868 KB
testcase_04 WA -
testcase_05 WA -
testcase_06 RE -
testcase_07 RE -
testcase_08 WA -
testcase_09 WA -
testcase_10 WA -
testcase_11 WA -
testcase_12 WA -
testcase_13 AC 146 ms
52,456 KB
testcase_14 RE -
testcase_15 WA -
testcase_16 RE -
testcase_17 WA -
testcase_18 WA -
testcase_19 WA -
testcase_20 WA -
testcase_21 AC 125 ms
52,704 KB
testcase_22 AC 182 ms
58,200 KB
testcase_23 AC 160 ms
52,568 KB
testcase_24 WA -
testcase_25 WA -
testcase_26 WA -
testcase_27 WA -
testcase_28 WA -
testcase_29 AC 88 ms
51,460 KB
testcase_30 AC 82 ms
51,048 KB
testcase_31 AC 72 ms
50,988 KB
testcase_32 WA -
testcase_33 WA -
testcase_34 WA -
testcase_35 AC 74 ms
51,112 KB
testcase_36 AC 80 ms
51,268 KB
testcase_37 WA -
testcase_38 WA -
testcase_39 WA -
testcase_40 WA -
testcase_41 WA -
testcase_42 WA -
testcase_43 RE -
testcase_44 WA -
testcase_45 WA -
testcase_46 WA -
testcase_47 WA -
testcase_48 WA -
testcase_49 WA -
testcase_50 WA -
testcase_51 RE -
testcase_52 WA -
testcase_53 WA -
testcase_54 WA -
testcase_55 RE -
testcase_56 WA -
testcase_57 WA -
testcase_58 AC 71 ms
50,820 KB
testcase_59 WA -
testcase_60 WA -
testcase_61 WA -
testcase_62 AC 71 ms
50,924 KB
testcase_63 AC 72 ms
51,056 KB
testcase_64 WA -
testcase_65 AC 71 ms
51,160 KB
testcase_66 WA -
testcase_67 AC 71 ms
51,052 KB
testcase_68 WA -
testcase_69 RE -
testcase_70 AC 92 ms
51,032 KB
testcase_71 WA -
testcase_72 AC 82 ms
51,288 KB
testcase_73 AC 91 ms
51,468 KB
testcase_74 RE -
testcase_75 RE -
testcase_76 WA -
testcase_77 WA -
testcase_78 RE -
testcase_79 AC 121 ms
52,088 KB
testcase_80 WA -
testcase_81 AC 126 ms
52,612 KB
testcase_82 WA -
権限があれば一括ダウンロードができます

ソースコード

diff #

import java.awt.Point;
import java.util.ArrayList;
import java.util.BitSet;
import java.util.HashSet;
import java.util.PriorityQueue;

public class Main {

	public static void main(String[] args) {
		new Main();
	}

	public Main() {
		FastScanner fs = new FastScanner();
		java.io.PrintWriter out = new java.io.PrintWriter(System.out);
		solve(fs, out);
		out.flush();
		//if (fs.hasNext()) throw new AssertionError("read input");
	}

	public void solve(FastScanner fs, java.io.PrintWriter out) {
		/*
		 * まず、最短経路ははい
		 * さて、2番目の候補は何か?
		 * ・ どこかの電線を使わない(INF)として、その頂点のX側の端点からゴールまでを再計算する
		 * 使わないもの決め打ちにO(N)、最短経路をO((M+N)logM)としてO(N(M+N)logM)とか
		 * ただ、これはTLEが怖いのよね
		 * さて、ではどうするべきか?
		 * ゴールに近い方から最短経路を求めるとする
		 * ただし、この時今まで使った辺は全てINFとする
		 * すると、この候補は今まで通った頂点(既に計算済み)+新しい経路(INFの方で計算した)の合成と表せる
		 * すると、次の候補は高々K-1個作られる(それ以外?どうせ答えじゃないから消しておk)
		 * 後は再帰的にはい
		 * 計算量はO(K^2(N+M)logM)
		 *
		 */
		int N = fs.nextInt(), M = fs.nextInt(), K = fs.nextInt();
		int X = fs.nextInt() - 1, Y = fs.nextInt() - 1;
		Point[] p = new Point[N];
		for (int i = 0;i < N;++ i) p[i] = new Point(fs.nextInt(),fs.nextInt());
		ArrayList<ArrayList<Integer>> graph = new ArrayList<ArrayList<Integer>>();
		for (int i = 0;i < N;++ i) graph.add(new ArrayList<>());
		for (int i = 0;i < M;++ i) {
			int P = fs.nextInt() - 1, Q = fs.nextInt() - 1;
			graph.get(P).add(Q);
			graph.get(Q).add(P);
		}
		PriorityQueue<Path> pq = new PriorityQueue<Path>((l, r) -> Double.compare(l.distance[Y], r.distance[Y]));
		{
			Path put = new Path();
			put.distance = dijkstra(graph, X, Y, p, new Path());
			{
				int now = Y;
				BitSet use = new BitSet(p.length);
				while(now != X) {
					use.set(now);
					int min = now;
					for (int i : graph.get(now)) if (!use.get(i) && (min == now || put.distance[min] > put.distance[i])) min = i;
					if (min == now) System.exit(1);
					put.path.add(now * 5000 + min);
					put.path.add(min * 5000 + now);
					now = min;
				}
			}
			pq.add(put);
		}
		final double[] INFS = new double[N];
		java.util.Arrays.fill(INFS, 1e18);
		for (int i = 0;i < K;++ i) {
			final Path ans = pq.poll();
			if (ans == null) {
				System.out.println(-1);
				continue;
			}
			System.out.println(ans.distance[Y]);
			double[] dist = dijkstra(graph, Y, X, p, ans);
			PriorityQueue<Integer> next = new PriorityQueue<>((l, r) -> Double.compare(ans.distance[l] + dist[l], ans.distance[r] + dist[r]));
			for (int j = 0;j < N;++ j) {
				if (j == X || j == Y || dist[j] > 1e17) continue;
				next.add(j);
			}
			for (int j = i;j < K && !next.isEmpty();++ j) {
				int tmp = next.poll();
				Path put = new Path();
				put.distance = java.util.Arrays.copyOf(INFS, N);
				{
					int now = tmp;
					BitSet use = new BitSet(p.length);
					while(now != X) {
						use.set(now);
						put.distance[now] = ans.distance[now];
						int min = now;
						for (int k : graph.get(now)) if (!use.get(k) && (min == now || ans.distance[min] > ans.distance[k])) min = k;
						if (min == now) System.exit(1);
						put.path.add(now * 5000 + min);
						put.path.add(min * 5000 + now);
						now = min;
					}
					put.distance[X] = 0;
				}
				{
					int now = tmp;
					BitSet use = new BitSet(p.length);
					while(now != Y) {
						use.set(now);
						put.distance[now] = ans.distance[tmp] + dist[tmp] - dist[now];
						int min = now;
						for (int k : graph.get(now)) if (!use.get(k) && (min == now || dist[min] > dist[k])) min = k;
						if (min == now) System.exit(1);
						put.path.add(now * 5000 + min);
						put.path.add(min * 5000 + now);
						now = min;
					}
					put.distance[Y] = ans.distance[tmp] + dist[tmp];
				}
				pq.add(put);
			}
		}
	}

	double[] dijkstra(ArrayList<ArrayList<Integer>> graph, int s, int t, Point[] p, Path ban) {
		double[] dist = new double[graph.size()];
		java.util.Arrays.fill(dist, 1e18);
		dist[s] = 0;
		PriorityQueue<Dist> pq = new PriorityQueue<>((l, r) -> Double.compare(l.dist, r.dist));
		BitSet use = new BitSet(p.length);
		pq.add(new Dist(s, s, 0));
		while(!pq.isEmpty()) {
			Dist tmp = pq.poll();
			if (use.get(tmp.next)) continue;
			use.set(tmp.next);
			if (tmp.next == t) break;
			for (int i : graph.get(tmp.next)) {
				if (ban.path.contains(i * 5000 + tmp.next)) continue;
				double d = dist[tmp.next] + distance(p[tmp.next], p[i]);
				if (dist[i] + 0.000000001 > d) {
					dist[i] = d;
					pq.add(new Dist(tmp.next, i, d));
				}
			}
		}
		return dist;
	}

	double distance(Point p1, Point p2) {
		return Math.sqrt(Math.pow(p1.x - p2.x, 2) + Math.pow(p1.y - p2.y, 2));
	}

	class Path {
		double[] distance;
		HashSet<Integer> path = new HashSet<>();
	}

	class Dist {
		final int last, next;
		final double dist;
		Dist(int l, int n, double d) {
			last = l;
			next = n;
			dist = d;
		}
	}

	static class FastScanner {
		private final java.io.InputStream in = System.in;
		private final byte[] buffer = new byte[1024];
		private int ptr = 0;
		private int buflen = 0;
		private boolean hasNextByte() {
			if (ptr < buflen) return true;
			ptr = 0;
			try {
				buflen = in.read(buffer);
			} catch (java.io.IOException e) {
				e.printStackTrace();
			}
			return buflen > 0;
		}
		private byte readByte() {
			return hasNextByte() ? buffer[ptr++ ] : -1;
		}
		private static boolean isPrintableChar(byte c) {
			return 32 < c || c < 0;
		}
		private static boolean isNumber(int c) {
			return '0' <= c && c <= '9';
		}
		public boolean hasNext() {
			while (hasNextByte() && !isPrintableChar(buffer[ptr])) ptr++ ;
			return hasNextByte();
		}
		public String next() {
			if (!hasNext()) throw new java.util.NoSuchElementException();
			StringBuilder sb = new StringBuilder();
			byte b;
			while (isPrintableChar(b = readByte())) sb.appendCodePoint(b);
			return sb.toString();
		}
		public final long nextLong() {
			if (!hasNext()) throw new java.util.NoSuchElementException();
			long n = 0;
			try {
				byte b = readByte();
				if (b == '-') {
					while(isNumber(b = readByte())) n = n * 10 + '0' - b;
					return n;
				} else if (!isNumber(b)) throw new NumberFormatException();
				do n = n * 10 + b - '0'; while (isNumber(b = readByte()));
			} catch (java.util.NoSuchElementException e) {
			}
			return n;
		}
		public final int nextInt() {
			if (!hasNext()) throw new java.util.NoSuchElementException();
			int n = 0;
			try {
				byte b = readByte();
				if (b == '-') {
					while(isNumber(b = readByte())) n = n * 10 + '0' - b;
					return n;
				} else if (!isNumber(b)) throw new NumberFormatException();
				do n = n * 10 + b - '0'; while (isNumber(b = readByte()));
			} catch (java.util.NoSuchElementException e) {
			}
			return n;
		}
		public double nextDouble() {
			return Double.parseDouble(next());
		}
	}
	public static class Arrays {
		public static void sort(final int[] array) {
			int l, min = 0xFFFFFFFF, max = 0;
			for (l = 0;l < array.length;++ l) {
				int i = array[l];
				min &= i;
				max |= i;
				if ((i & 0x80000000) == 0) break;
			}
			for (int r = l + 1;r < array.length;++ r) {
				int i = array[r];
				min &= i;
				max |= i;
				if ((i & 0x80000000) != 0) {
					array[r] = array[l];
					array[l ++] = i;
				}
			}
			int use = min ^ max, bit = Integer.highestOneBit(use & 0x7FFFFFFF);
			if (bit == 0) return;
			sort(array, 0, l, use, bit);
			sort(array, l, array.length, use, bit);
		}
		private static void sort(final int[] array, final int left, final int right, final int use, int digit) {
			if (right - left <= 96) {
				for (int i = left + 1;i < right;++ i) {
					int tmp = array[i], tmp2, j;
					for (j = i;j > left && (tmp2 = array[j - 1]) > tmp;-- j) array[j] = tmp2;
					array[j] = tmp;
				}
				return;
			}
			int l = left;
			while(l < right && (array[l] & digit) == 0) ++ l;
			for (int r = l + 1;r < right;++ r) {
				int i = array[r];
				if ((i & digit) == 0) {
					array[r] = array[l];
					array[l ++] = i;
				}
			}
			if ((digit = Integer.highestOneBit(use & digit - 1)) == 0) return;
			sort(array, left, l, use, digit);
			sort(array, l, right, use, digit);
		}
		public static void sort(final long[] array) {
			int l;
			long min = 0xFFFFFFFFFFFFFFFFL, max = 0;
			for (l = 0;l < array.length;++ l) {
				long i = array[l];
				min &= i;
				max |= i;
				if ((i & 0x8000000000000000L) == 0) break;
			}
			for (int r = l + 1;r < array.length;++ r) {
				long i = array[r];
				min &= i;
				max |= i;
				if ((i & 0x8000000000000000L) != 0) {
					array[r] = array[l];
					array[l ++] = i;
				}
			}
			long use = min ^ max, bit = Long.highestOneBit(use & 0x7FFFFFFFFFFFFFFFL);
			if (bit == 0) return;
			sort(array, 0, l, use, bit);
			sort(array, l, array.length, use, bit);
		}
		private static void sort(final long[] array, final int left, final int right, final long use, long digit) {
			if (right - left <= 96) {
				for (int i = left + 1, j;i < right;++ i) {
					long tmp = array[i], tmp2;
					for (j = i;j > left && (tmp2 = array[j - 1]) > tmp;-- j) array[j] = tmp2;
					array[j] = tmp;
				}
				return;
			}
			int l = left;
			while(l < right && (array[l] & digit) == 0) ++ l;
			for (int r = l + 1;r < right;++ r) {
				long i = array[r];
				if ((i & digit) == 0) {
					array[r] = array[l];
					array[l ++] = i;
				}
			}
			if ((digit = Long.highestOneBit(use & digit - 1)) == 0) return;
			sort(array, left, l, use, digit);
			sort(array, l, right, use, digit);
		}
	}

	public static class IntMath {
		public static int gcd(int a, int b) {
			while (a != 0) if ((b %= a) != 0) a %= b; else return a;
			return b;
		}
		public static int gcd(int... array) {
			int ret = array[0];
			for (int i = 1;i < array.length;++ i) ret = gcd(ret, array[i]);
			return ret;
		}
		public static long gcd(long a, long b) {
			while (a != 0) if ((b %= a) != 0) a %= b; else return a;
			return b;
		}
		public static long gcd(long... array) {
			long ret = array[0];
			for (int i = 1;i < array.length;++ i) ret = gcd(ret, array[i]);
			return ret;
		}
		public static long lcm(long a, long b) {
			return a / gcd(a, b) * b;
		}
		public static int pow(int a, int b) {
			int ans = 1;
			for (int mul = a;b > 0;b >>= 1, mul *= mul) if ((b & 1) != 0) ans *= mul;
			return ans;
		}
		public static long powLong(int a, int b) {
			long ans = 1;
			for (int mul = a;b > 0;b >>= 1, mul *= mul) if ((b & 1) != 0) ans *= mul;
			return ans;
		}
		public static int pow(int a, int b, int mod) {
			if (b < 0) b = b % (mod - 1) + mod - 1;
			long ans = 1;
			for (long mul = a;b > 0;b >>= 1, mul = mul * mul % mod) if ((b & 1) != 0) ans = ans * mul % mod;
			return (int)ans;
		}
		public static int floorsqrt(long n) {
			return (int)Math.sqrt(n + 0.1);
		}
		public static int ceilsqrt(long n) {
			return n <= 1 ? (int)n : (int)Math.sqrt(n - 0.1) + 1;
		}
	}
}
0