結果

問題 No.382 シャイな人たち (2)
ユーザー 37zigen37zigen
提出日時 2016-06-25 13:27:01
言語 Java21
(openjdk 21)
結果
WA  
実行時間 -
コード長 14,886 bytes
コンパイル時間 2,934 ms
コンパイル使用メモリ 92,344 KB
実行使用メモリ 77,180 KB
最終ジャッジ日時 2024-04-20 02:44:50
合計ジャッジ時間 73,563 ms
ジャッジサーバーID
(参考情報)
judge5 / judge4
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 3,581 ms
73,884 KB
testcase_01 AC 3,692 ms
74,932 KB
testcase_02 AC 3,495 ms
74,320 KB
testcase_03 AC 3,317 ms
73,664 KB
testcase_04 AC 3,009 ms
73,972 KB
testcase_05 AC 3,407 ms
75,116 KB
testcase_06 AC 3,151 ms
77,180 KB
testcase_07 AC 3,620 ms
75,000 KB
testcase_08 WA -
testcase_09 AC 2,844 ms
74,008 KB
testcase_10 AC 3,242 ms
75,924 KB
testcase_11 AC 4,632 ms
77,140 KB
testcase_12 AC 2,572 ms
73,860 KB
testcase_13 AC 2,989 ms
73,936 KB
testcase_14 AC 2,962 ms
75,024 KB
testcase_15 WA -
testcase_16 AC 3,081 ms
74,960 KB
testcase_17 WA -
testcase_18 AC 3,097 ms
74,484 KB
testcase_19 AC 3,557 ms
76,032 KB
testcase_20 AC 146 ms
54,592 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);
					if(is_deg_correct(e, deg)){
						throw new AssertionError();
					}
					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){
				System.err.println("e[A].size()="+e[A].size());
				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();
			}
			if (e[B2].contains(B)) {
				g.delete_v_with_neighbours(A);
				if(is_deg_correct(e, deg)){
					throw new AssertionError();
				}
				Pair p = ms(g);
				p.cardinality++;
				p.choosed_vertices[A] = true;
				return p;
			}

			Graph g2 = g.copy();
			g2.delete_v_with_neighbours(B);
			g2.delete_v_with_neighbours(B2);
			if(is_deg_correct(e, deg)){
				throw new AssertionError();
			}
			Pair p = ms(g2);
			p.cardinality += 2;
			p.choosed_vertices[B] = true;
			p.choosed_vertices[B2] = true;
			ArrayList<Integer> neighbour = new ArrayList<>();
			for (int i = 0; i < 2; i++) {
				int u = (i == 0 ? B : B2);// u is an element of N(A)
				for (int j = 0; j < e[u].size(); j++) {
					int v = e[u].get(j);
					if (v == A)
						continue;
					if (neighbour.contains(v))
						continue;
					neighbour.add(v);
				}
			}
			g.delete_v_with_neighbours(A);
			Pair p2 = ms2(g, neighbour);
			p2.cardinality++;
			p2.choosed_vertices[A] = true;
			p = pair_bigger(p, p2);
			return p;
		}
		if (deg[A] == 3) {
			Graph g2 = g.copy();
			g2.delete_v_with_neighbours(A);
			if(is_deg_correct(e, deg)){
				throw new AssertionError();
			}
			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, 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);

		if(is_deg_correct(e, deg)){
			throw new AssertionError();
		}
		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;
		}
	}

	// Sから少なくとも二つ使う場合を考える。
	Pair ms2(Graph g, ArrayList<Integer> S) {
		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]);
		if (S.size()<= 1)
			return p;
		if (S.size() == 2) {
			int u = S.get(0);
			int v = S.get(1);
			if (e[u].contains(v))
				return p;
			else {
				g.delete_v_with_neighbours(u);
				g.delete_v_with_neighbours(v);
				p = ms(g);
				p.cardinality += 2;
				p.choosed_vertices[u] = true;
				p.choosed_vertices[v] = true;
				return p;
			}
		}
		if (S.size() == 3) {
			int[] s = new int[3];
			for (int i = 0; i < 3; i++) {
				s[i] = S.get(i);
			}
			// arrange s[i] so that s[0] is the smallest one;
			if (deg[s[0]] > deg[s[1]]) {
				int d = s[0];
				s[0] = s[1];
				s[1] = d;
			}
			if (deg[s[0]] > deg[s[2]]) {
				int d = s[0];
				s[0] = s[2];
				s[2] = d;
			}
			if (deg[s[0]] == 0) {
				g.delete_v_with_neighbours(s[0]);
				S.remove((Integer) s[0]);
				p = ms1(g, S);
				p.cardinality++;
				p.choosed_vertices[s[0]] = true;
			}
			if (e[s[0]].contains(s[1]) && e[s[1]].contains(s[2]) && e[s[2]].contains(s[1])) {
				return p;
			}
			for (int i = 0; i < 3; i++) {
				int u = s[(i + 1) % 3];
				int v = s[(i + 2) % 3];

				if (e[u].contains(s[i]) && e[s[i]].contains(v)) {
					g.delete_v_with_neighbours(u);
					g.delete_v_with_neighbours(v);
					p = ms(g);
					p.cardinality += 2;
					p.choosed_vertices[u] = true;
					p.choosed_vertices[v] = true;
					return p;
				}
			}
			for (int i = 0; i < 3; i++) {
				int u = s[(i + 1) % 3];
				int v = s[(i + 2) % 3];
				if (e[u].contains(s[i])) {
					g.delete_v_with_neighbours(v);
					S.remove((Integer) v);
					p = ms1(g, S);
					p.cardinality++;
					p.choosed_vertices[v] = true;
					return p;
				} else if (e[v].contains(s[i])) {
					g.delete_v_with_neighbours(u);
					S.remove((Integer) u);
					p = ms1(g, S);
					p.cardinality++;
					p.choosed_vertices[u] = true;
					return p;
				}
			}
			for (int i = 0; i < 3; i++) {
				int u = s[i];
				int v = s[(i + 1) % 3];
				for (int j = 0; j < e[u].size(); j++) {
					int w = e[u].get(j);
					if (e[v].contains(w)) {
						g.delete_vertice(w);
						if(is_deg_correct(e, deg)){
							throw new AssertionError();
						}
						p = ms2(g, S);
						return p;
					}
				}
			}
			if (deg[s[0]] == 1) {
				g.delete_v_with_neighbours(s[0]);
				S.remove((Integer) s[0]);
				if(is_deg_correct(e, deg)){
					throw new AssertionError();
				}
				p = ms1(g, S);
				p.cardinality++;
				p.choosed_vertices[s[0]] = true;
				return p;
			}
			Graph g2 = g.copy();
			g2.delete_v_with_neighbours(s[0]);
			S.remove((Integer) s[0]);
			p = ms1(g2, S);
			p.cardinality++;
			p.choosed_vertices[s[0]] = true;
			g.delete_v_with_neighbours(s[2]);
			g.delete_v_with_neighbours(s[1]);
			g.delete_vertice(s[0]);
			Pair p2 = ms2(g, e[s[0]]);
			p = pair_bigger(p, p2);
			return p;
		}
		if (S.size() == 4) {
			int min_v = S.get(0);
			for (int i = 0; i < 4; i++) {
				int v = S.get(i);
				if (deg[v] < deg[min_v]) {
					min_v = v;
				}
			}
			if (deg[min_v] <= 3) {
				return ms(g);
			} else {
				Graph g2 = g.copy();

				g.delete_v_with_neighbours(min_v);
				p = ms(g);
				p.cardinality++;
				p.choosed_vertices[min_v] = true;

				g2.delete_vertice(min_v);
				S.remove((Integer) min_v);
				Pair p2 = ms2(g2, S);
				p = pair_bigger(p, p2);
				return p;

			}
		}
		return ms(g);
	}

	Pair ms1(Graph g, ArrayList<Integer> S) {
		int[] deg = g.deg;
		ArrayList<Integer>[] e = g.e;
		boolean[] valid_vertices = g.valid_vertices;
		int n = g.n;

		if (S.size() != 2) {
			throw new AssertionError("S.size()!=2");
		}
		int s1 = S.get(0);
		int s2 = S.get(1);
		if (deg[s1] > deg[s2]) {
			int d = s1;
			s1 = s2;
			s2 = d;
		}

		if(is_deg_correct(e, deg)){
			throw new AssertionError();
		}
		if (deg[s1] <= 1) {
			return ms(g);
		}else if (e[s1].contains(s2)) {
			if (deg[s1] <= 3)
				return ms(g);
			else{
				Graph g2=g.copy();

				g.delete_v_with_neighbours(s1);
				g2.delete_v_with_neighbours(s2);

				Pair p1=ms(g);
				p1.cardinality++;
				p1.choosed_vertices[s1]=true;

				Pair p2=ms(g2);
				p2.cardinality++;
				p2.choosed_vertices[s2]=true;
				return pair_bigger(p1, p2);

			}
		}
		if(is_deg_correct(e, deg)){
			throw new AssertionError();
		}
		ArrayList<Integer> intersection=intersection(e[s1],e[s2]);
		if(intersection.size()!=0){
			for(int i=0;i<intersection.size();i++){
				g.delete_vertice(intersection.get(i));
			}
			return ms1(g,S);
		}else if(deg[s2]==2){
			if(is_deg_correct(e, deg)){
				throw new AssertionError();
			}
			if(deg[s1]!=2){
				throw new AssertionError("deg[s1]!=2");
			}
			int E=e[s1].get(0);
			int F=e[s2].get(1);
			if(is_deg_correct(e, deg)){
				throw new AssertionError();
			}
			if(e[E].contains(F)){
				g.delete_v_with_neighbours(s1);
				Pair p=ms(g);
				p.cardinality++;
				p.choosed_vertices[s1]=true;
				return p;
			}
			if(is_deg_correct(e, deg)){
				throw new AssertionError();
			}
			ArrayList<Integer> union=union(e[E],e[F]);
			if(is_deg_correct(e, deg)){
				throw new AssertionError();
			}
			union.remove((Integer)s1);
			if(is_deg_correct(e, deg)){
				throw new AssertionError();
			}
			if(is_subset(union,e[s2])){
				g.delete_v_with_neighbours(s1);
				g.delete_v_with_neighbours(s2);
				Pair p=ms(g);
				p.cardinality+=3;
				p.choosed_vertices[E]=true;
				p.choosed_vertices[F]=true;
				p.choosed_vertices[s2]=true;
				return p;
			}else{
				Graph g2=g.copy();

				g.delete_v_with_neighbours(s1);
				g.delete_v_with_neighbours(s2);
				if(is_deg_correct(e, deg)){
					throw new AssertionError();
				}
				Pair p=ms(g);
				p.cardinality+=3;
				p.choosed_vertices[E]=true;
				p.choosed_vertices[F]=true;
				p.choosed_vertices[s2]=true;

				g2.delete_v_with_neighbours(s1);
				Pair p2=ms(g2);
				p2.cardinality++;
				p2.choosed_vertices[s1]=true;

				return pair_bigger(p,p2);
			}
			
		}else{
			Graph g2=g.copy();

			if(is_deg_correct(e, deg)){
				throw new AssertionError();
			}
			g.delete_v_with_neighbours(s2);
			Pair p=ms(g);

			g2.delete_v_with_neighbours(s1);
			g2.delete_vertice(s2);
			Pair p2=ms2(g2,e[s2]);
			p2.cardinality++;
			p2.choosed_vertices[s1]=true;
			p=pair_bigger(p, p2);
			return p;
		}
	}
	@SuppressWarnings({ "rawtypes", "unchecked" })
	ArrayList intersection(ArrayList s1,ArrayList s2){
		ArrayList ret=new ArrayList<>();
		for(int i=0;i<s1.size();i++){
			if(s2.contains(s1.get(i))){
				ret.add(s1.get(i));
			}
		}
		return ret;
	}

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

	boolean is_subset(ArrayList<Integer> subset,ArrayList<Integer> superset){
		if(subset.size()>superset.size())
			return false;
		for(int i=0;i<subset.size();i++){
			if(!superset.contains(subset)){
				return false;
			}
		}
		return true;
	}
	ArrayList<Integer> union(ArrayList<Integer> s1,ArrayList<Integer> s2){
		ArrayList<Integer> ret=new ArrayList<>();
		for(int i=0;i<s1.size();i++){
			if(!ret.contains(s1.get(i))){
				ret.add(s1.get(i));
			}
		}
		for(int i=0;i<s2.size();i++){
			if(!ret.contains(s2.get(i))){
				ret.add(s2.get(i));
			}
		}
		return s2;
	}

	//正しくないときにtrueを返す
	boolean is_deg_correct(ArrayList<Integer>[] e,int[] deg){
		for(int i=0;i<deg.length;i++){
			if(deg[i]!=e[i].size())
				return true;
		}
		return false;
	}
}
0