結果

問題 No.1069 電柱 / Pole (Hard)
ユーザー CuriousFairy315CuriousFairy315
提出日時 2020-05-29 23:08:49
言語 Java21
(openjdk 21)
結果
WA  
実行時間 -
コード長 11,162 bytes
コンパイル時間 3,237 ms
コンパイル使用メモリ 98,748 KB
実行使用メモリ 60,576 KB
最終ジャッジ日時 2024-11-06 12:10:59
合計ジャッジ時間 7,555 ms
ジャッジサーバーID
(参考情報)
judge2 / judge3
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 72 ms
51,092 KB
testcase_01 AC 72 ms
50,952 KB
testcase_02 AC 71 ms
50,676 KB
testcase_03 AC 71 ms
50,728 KB
testcase_04 WA -
testcase_05 WA -
testcase_06 TLE -
testcase_07 -- -
testcase_08 -- -
testcase_09 -- -
testcase_10 -- -
testcase_11 -- -
testcase_12 -- -
testcase_13 -- -
testcase_14 -- -
testcase_15 -- -
testcase_16 -- -
testcase_17 -- -
testcase_18 -- -
testcase_19 -- -
testcase_20 -- -
testcase_21 -- -
testcase_22 -- -
testcase_23 -- -
testcase_24 -- -
testcase_25 -- -
testcase_26 -- -
testcase_27 -- -
testcase_28 -- -
testcase_29 -- -
testcase_30 -- -
testcase_31 -- -
testcase_32 -- -
testcase_33 -- -
testcase_34 -- -
testcase_35 -- -
testcase_36 -- -
testcase_37 -- -
testcase_38 -- -
testcase_39 -- -
testcase_40 -- -
testcase_41 -- -
testcase_42 -- -
testcase_43 -- -
testcase_44 -- -
testcase_45 -- -
testcase_46 -- -
testcase_47 -- -
testcase_48 -- -
testcase_49 -- -
testcase_50 -- -
testcase_51 -- -
testcase_52 -- -
testcase_53 -- -
testcase_54 -- -
testcase_55 -- -
testcase_56 -- -
testcase_57 -- -
testcase_58 -- -
testcase_59 -- -
testcase_60 -- -
testcase_61 -- -
testcase_62 -- -
testcase_63 -- -
testcase_64 -- -
testcase_65 -- -
testcase_66 -- -
testcase_67 -- -
testcase_68 -- -
testcase_69 -- -
testcase_70 -- -
testcase_71 -- -
testcase_72 -- -
testcase_73 -- -
testcase_74 -- -
testcase_75 -- -
testcase_76 -- -
testcase_77 -- -
testcase_78 -- -
testcase_79 -- -
testcase_80 -- -
testcase_81 -- -
testcase_82 -- -
権限があれば一括ダウンロードができます

ソースコード

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;
					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