結果

問題 No.382 シャイな人たち (2)
ユーザー 37zigen37zigen
提出日時 2016-06-24 12:40:34
言語 Java21
(openjdk 21)
結果
AC  
実行時間 6,190 ms / 8,000 ms
コード長 8,217 bytes
コンパイル時間 2,456 ms
コンパイル使用メモリ 82,400 KB
実行使用メモリ 73,436 KB
最終ジャッジ日時 2023-08-02 00:56:13
合計ジャッジ時間 113,724 ms
ジャッジサーバーID
(参考情報)
judge14 / judge11
このコードへのチャレンジ(β)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 6,190 ms
71,832 KB
testcase_01 AC 5,996 ms
70,304 KB
testcase_02 AC 5,207 ms
72,256 KB
testcase_03 AC 5,714 ms
73,436 KB
testcase_04 AC 4,564 ms
72,064 KB
testcase_05 AC 5,302 ms
72,280 KB
testcase_06 AC 4,523 ms
72,632 KB
testcase_07 AC 5,372 ms
72,096 KB
testcase_08 AC 4,202 ms
72,372 KB
testcase_09 AC 6,091 ms
71,944 KB
testcase_10 AC 4,759 ms
72,448 KB
testcase_11 AC 5,481 ms
72,148 KB
testcase_12 AC 4,618 ms
72,176 KB
testcase_13 AC 5,838 ms
69,900 KB
testcase_14 AC 5,114 ms
70,192 KB
testcase_15 AC 5,688 ms
71,952 KB
testcase_16 AC 3,975 ms
72,676 KB
testcase_17 AC 3,739 ms
71,440 KB
testcase_18 AC 5,643 ms
72,192 KB
testcase_19 AC 5,398 ms
72,432 KB
testcase_20 AC 135 ms
56,188 KB
権限があれば一括ダウンロードができます

ソースコード

diff #

package yukicoder;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Scanner;
import java.util.Set;

public class Main {
	public static void main(String[] args) {

		new Main().solver();
		// new Q382().trial();

	}

	void trial() {
		Scanner sc = new Scanner(System.in);

		int N = sc.nextInt();
		int[] d = new int[N - 1];
		for (int i = 0; i < N - 1; i++) {
			d[i] = sc.nextInt();
		}
		Arrays.sort(d);
		for (int i = 0; i < N - 1; i++) {
			System.out.println(d[i]);
		}
	}

	void solver() {
		Scanner sc = new Scanner(System.in);
		long S = sc.nextLong();
		long Start = System.currentTimeMillis();
		Graph g = set_edge(S);
		Pair p = ms(g);
		int n = g.n;
		if (p.cardinality == n) {
			System.out.println(-1);
		} else {
			System.out.println((p.cardinality + 1));
			boolean f = false;
			for (int i = 0; i < p.choosed_vertices.length; i++) {
				if (p.choosed_vertices[i]) {
					System.out.print((!f ? "" : " ") + (i + 1));
					f = true;
				}
			}
			System.out.println();
		}

		long T = System.currentTimeMillis();
		System.err.println((T - Start) + "ms");
	}

	final long MOD = 1000003;

	Graph set_edge(long S) {
		S = (S * 12345) % MOD;
		int N = (int) (S % 120) + 2;
		Graph g = new Graph(N);
		S = (S * 12345) % MOD;
		long P = S;
		for (int i = 0; i < N; i++) {
			for (int j = i + 1; j < N; j++) {
				S = (S * 12345) % MOD;
				if (S >= P) {
					g.set_edge(i, j);
				}
			}
		}
		return g;
	}

	// 無向グラフ
	class Graph {
		ArrayList<Integer>[] e;
		int n;
		int[] deg;
		boolean[] valid_vertices;// 選ぶことのできる頂点
		boolean[] choosed_vertices;// 選ばれた頂点

		Graph(int n) {
			this.n = n;
			deg = new int[n];
			valid_vertices = new boolean[n];
			choosed_vertices = new boolean[n];
			Arrays.fill(valid_vertices, true);
			e = new ArrayList[n];
			for (int i = 0; i < n; i++) {
				e[i] = new ArrayList<>();
			}
		}

		// 無向グラフの辺a<->を作成
		void set_edge(int a, int b) {
			if (!e[a].contains((Integer) b)) {
				e[a].add(b);
				e[b].add(a);
				deg[a]++;
				deg[b]++;
			}
		}

		// 辺a<->bを消去
		void delete_undirected_edge(int a, int b) {
			e[a].remove((Integer) b);
			e[b].remove((Integer) a);
			deg[a]--;
			deg[b]--;
		}

		// 頂点vを消去
		void delete_vertice(int v) {
			while (e[v].size() > 0) {
				int u = e[v].get(0);
				delete_undirected_edge(u, v);
			}
			valid_vertices[v] = false;
		}

		// 頂点vと、vの隣接頂点を消去
		void delete_v_with_neighbours(int v) {
			while (e[v].size() > 0) {
				int u = e[v].get(0);
				delete_vertice(u);
			}
			delete_vertice(v);
		}

		// deep copy
		Graph copy() {
			Graph g = new Graph(this.n);
			for (int i = 0; i < n; i++) {
				g.deg[i] = deg[i];
			}
			for (int i = 0; i < n; i++) {
				g.valid_vertices[i] = valid_vertices[i];
			}
			for (int i = 0; i < n; i++) {
				for (int j = 0; j < e[i].size(); j++) {
					(g.e[i]).add(e[i].get(j));
				}
			}
			return g;
		}
	}

	Pair ms(Graph g) {

		int[] deg = g.deg;
		ArrayList<Integer>[] e = g.e;
		boolean[] valid_vertices = g.valid_vertices;
		int n = g.n;
		int A = -1;// 最も次数の小さい頂点
		int B = -1;// Aにつながる頂点のうち最も次数の大きいもの
		int deg_me_min = Integer.MAX_VALUE / 4;
		int deg_to_max = -Integer.MAX_VALUE / 4;
		for (int i = 0; i < n; i++) {
			if (!valid_vertices[i])
				continue;
			if (deg[i] < deg_me_min) {
				A = i;
				deg_me_min = deg[A];
				if (deg_me_min <= 1) {
					g.delete_v_with_neighbours(A);
					Pair p = ms(g);
					p.choosed_vertices[A] = true;
					p.cardinality++;
					return p;
				}
				B = e[A].get(0);
				deg_to_max = deg[B];
				for (int j = 1; j < e[A].size(); j++) {
					int u = e[A].get(j);
					if (deg[u] > deg_to_max) {
						B = u;
						deg_to_max = deg[B];
					}
				}
			} else if (deg[i] == deg_me_min) {
				for (int j = 0; j < e[A].size(); j++) {
					int u = e[A].get(j);
					if (deg[u] > deg_to_max) {
						A = i;
						B = u;
						deg_to_max = deg[B];
					}
				}
			}
		}

		if (A == -1 && B == -1)
			return new Pair(0, new boolean[n]);
		if (A == -1 || B == -1)
			throw new AssertionError("A==-1||B==-1");
		if (deg[A] > deg[B])
			throw new AssertionError("deg[A]>deg[B]");
		if (deg[A] == 2) {
			int B2 = -1;
			if(e[A].size()!=2)
				throw new AssertionError("e[A].size!=2");
			if(e[A].get(0)!=B){
				B2=e[A].get(0);
			}else if(e[A].get(1)!=B){
				B2=e[A].get(1);
			}else{
				throw new AssertionError();
			}
			for(int i=0;i<e[B2].size();i++){
				int u=e[B2].get(i);
				if(u==B){
					g.delete_v_with_neighbours(A);
					Pair p=ms(g);
					p.cardinality++;
					p.choosed_vertices[A]=true;
					return p;
				}
			}
			
		}
		if (deg[A] == 3) {
			Graph g2 = g.copy();
			g2.delete_v_with_neighbours(A);
			Pair p2 = ms(g2);
			p2.cardinality++;
			p2.choosed_vertices[A] = true;

			ArrayList<Integer> d = new ArrayList<>();
			for (int i = 0; i < e[A].size(); i++) {
				d.add(e[A].get(i));
			}
			g.delete_vertice(A);
			Pair p1 = ms2(g, A, 0, d);
			return pair_bigger(p1, p2);
		}
		// else if (dominance(B, A, g)) {
		// g.delete_vertice(B);
		// Pair p = ms(g);
		// p.cardinality++;
		// p.choosed_vertices[B] = true;
		// return p;
		// }
		Graph g2 = g.copy();
		g2.delete_v_with_neighbours(B);
		g.delete_vertice(B);
		Pair p1 = ms(g);
		Pair p2 = ms(g2);
		p2.cardinality++;
		p2.choosed_vertices[B] = true;
		if (p1.cardinality > p2.cardinality) {
			return p1;
		} else {
			return p2;
		}
	}

	// 頂点vの隣接頂点から少なくとも二つ使う場合を考える。
	// count==1なら2回目
	// count==0なら1回目
	Pair ms2(Graph g, int v, int count, ArrayList<Integer> neighbour) {
		int[] deg = g.deg;
		ArrayList<Integer>[] e = g.e;
		boolean[] valid_vertices = g.valid_vertices;
		int n = g.n;

		Pair p = new Pair(0, new boolean[n]);
		while (!neighbour.isEmpty()) {
			int u = neighbour.get(0);
			if (!valid_vertices[u]) {
				if (!neighbour.remove((Integer) u)) {
					throw new AssertionError("neighbour dosent have u");
				}
				if (count == 0)
					throw new AssertionError("error");
				continue;
			}
			if (deg[u] <= 1) {
				g.delete_v_with_neighbours(u);
				if (!neighbour.remove((Integer) u)) {
					throw new AssertionError("neighbour dosent have u");
				}
				if (count == 0) {
					Pair p1 = ms2(g, v, (count + 1), neighbour);
					p1.choosed_vertices[u] = true;
					p1.cardinality++;
					return p1;
				} else if (count == 1) {
					Pair p1 = ms(g);
					p1.choosed_vertices[u] = true;
					p1.cardinality++;
					return p1;
				} else {
					throw new AssertionError("error");
				}
			}
			Graph g2 = g.copy();
			g2.delete_v_with_neighbours(u);
			if (!neighbour.remove((Integer) u)) {
				throw new AssertionError("neighbour dosent have u");
			}

			if (count == 0) {
				Pair p2 = ms2(g2, v, (count + 1), neighbour);
				p2.choosed_vertices[u] = true;
				p2.cardinality++;
				p = pair_bigger(p, p2);
			} else if (count == 1) {
				Pair p2 = ms(g2);
				p2.choosed_vertices[u] = true;
				p2.cardinality++;
				p = pair_bigger(p, p2);

			} else {
				throw new AssertionError("error");
			}
		}
		if (neighbour.size() != 0) {
			throw new AssertionError("neighbour.size()==" + neighbour.size());
		}
		return p;
	}

	Pair pair_bigger(Pair p1, Pair p2) {
		return p1.cardinality > p2.cardinality ? p1 : p2;
	}

	class Pair {
		int cardinality;
		boolean[] choosed_vertices;

		Pair(int cardinality, boolean[] choosed_vertices) {
			this.cardinality = cardinality;
			this.choosed_vertices = choosed_vertices;
		}
	}

	// whethere N(B)&B is subset of N(A)&A or not;
	boolean dominance(int A, int B, Graph g) {
		Set<Integer>as = new HashSet<>();
		Set<Integer> bs = new HashSet<>();
		ArrayList<Integer>[] e = g.e;
		for (int i = 0; i < e[A].size(); i++) {
			as.add(e[A].get(i));
		}
		for (int i = 0; i < e[B].size(); i++) {
			bs.add(e[B].get(i));
		}

		if (!as.contains(B)) {
			as.add(B);
		}
		if (!bs.contains(A)) {
			bs.add(A);
		}

		if (as.size() < bs.size())
			return false;

		for (Iterator<Integer> it = bs.iterator(); it.hasNext();) {
			if (!as.contains(it.next())) {
				return false;
			}
		}
		return true;
	}
}
0