結果

問題 No.382 シャイな人たち (2)
ユーザー 37zigen37zigen
提出日時 2016-06-26 15:48:00
言語 Java21
(openjdk 21)
結果
TLE  
実行時間 -
コード長 16,886 bytes
コンパイル時間 3,264 ms
コンパイル使用メモリ 92,880 KB
実行使用メモリ 78,432 KB
最終ジャッジ日時 2024-04-20 04:30:57
合計ジャッジ時間 21,677 ms
ジャッジサーバーID
(参考情報)
judge4 / judge3
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 TLE -
testcase_01 -- -
testcase_02 -- -
testcase_03 -- -
testcase_04 -- -
testcase_05 -- -
testcase_06 -- -
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 -- -
権限があれば一括ダウンロードができます

ソースコード

diff #

package グラフ;

import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Scanner;

public class Main {
	//Pair p=mis(g)
	//p.cardinality:最大独立集合の頂点数
	//p.choosed_vertices:最大独立集合の頂点
	//120頂点で5秒ぐらい。
	//verified yukicoder No.382
	//
	public static void main(String[] args){
		new Main().solver();
	}


	void solver() {
		Scanner sc = new Scanner(System.in);
		while(sc.hasNext()){
			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");
		}
		sc.close();
	}

	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;// 選ばれた頂点
		long v=0;//選ばれた頂点。0は存在しない。1は存在。

		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<>();
			}
		}
		Graph[] disjoint_set() throws CloneNotSupportedException{
			int[] ds=new int[n];
			Arrays.fill(ds, -1);
			ArrayDeque<Integer> q=new ArrayDeque<>();
			int now=0;

			for(int i=0;i<n;i++){
				if(ds[i]==-1&&valid_vertices[i]){
					ds[i]=now;
					q.add(i);
					while(!q.isEmpty()){
						int v=q.poll();
						if(!valid_vertices[v])
							throw new AssertionError();
						ds[v]=now;
						for(int j=0;j<e[v].size();j++){
							int u=e[v].get(j);
							if(ds[u]==-1){
								ds[u]=now;
								q.add(u);
							}else if(ds[u]!=now){
								throw new AssertionError();
							}
						}
					}
					now++;
				}
			}
			for(int i=0;i<n;i++){
				if(ds[i]==-1)
					continue;
				for(int j=0;j<n;j++){
					if(edge(i,j,e)){
						if(ds[i]!=ds[j]){
							System.out.println(i+" "+j);
							System.out.println(ds[i]+" "+ds[j]);
							System.out.println(valid_vertices[i]+" "+valid_vertices[j]);
							throw new AssertionError();
						}
					}
				}
			}


			if(now==0){
				return new Graph[]{new Graph(0)};
			}else if(now==1){
				return new Graph[]{copy()};
			}
			Graph[] gs=new Graph[now];
			boolean[][] each_valid_vertices=new boolean[now][n];
			for(int i=0;i<n;i++){
				int d=ds[i];
				if(d==-1)continue;
				each_valid_vertices[d][i]=true;
			}


			for(int i=0;i<now;i++){
				gs[i]=induced_subgraph(each_valid_vertices[i]);
			}
			return gs;
		}

		// 無向グラフの辺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]++;
			}
		}

		private void delete_undirected_edge(int a, int b) {
			e[a].remove((Integer) b);
			e[b].remove((Integer) a);
			deg[a]--;
			deg[b]--;
		}

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

		void delete_v_with_neighbours(int v) {
			while (e[v].size() > 0) {
				int u = e[v].get(0);
				delete_vertice(u);
			}
			delete_vertice(v);
		}
		private Graph induced_subgraph(boolean[] valid_vertices){
			Graph g=copy();
			int n=g.n;
			for(int i=0;i<n;i++){
				g.valid_vertices[i]=this.valid_vertices[i];
			}
			for(int i=0;i<n;i++){
				if(!this.valid_vertices[i])
					continue;
				else if(this.valid_vertices[i]&&(!valid_vertices[i])){
					g.delete_vertice(i);
				}else if(this.valid_vertices[i]&&valid_vertices[i]){
					continue;
				}else{
					System.out.println(this.valid_vertices[i]);
					System.out.println(valid_vertices[i]);
					throw new AssertionError();
				}
			}
			return g;
		}

		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 n = g.n;
		try {
			Graph[] gs=g.disjoint_set();
			if(gs.length>=2){
				Pair p=new Pair(0,new boolean[n]);
				for(int i=0;i<gs.length;i++){
					p=pair_union(p,ms(gs[i]));
				}
				return p;
			}
		} catch (CloneNotSupportedException e1) {
			// TODO 自動生成された catch ブロック
			e1.printStackTrace();
		}

		int[] deg = g.deg;
		ArrayList<Integer>[] e = g.e;
		boolean[] valid_vertices = g.valid_vertices;
		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].get(0) != B) {
				B2 = e[A].get(0);
			} else if (e[A].get(1) != B) {
				B2 = e[A].get(1);
			}
			if (edge(B2,B,e)) {
				g.delete_v_with_neighbours(A);
				Pair p = ms(g);
				p.cardinality++;
				p.choosed_vertices[A] = true;
				return p;
			}else{

				Graph g2 = g.copy();
				g2.delete_v_with_neighbours(B);
				g2.delete_v_with_neighbours(B2);
				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);
			Pair p2 = ms(g2);
			p2.cardinality++;
			p2.choosed_vertices[A] = true;

			ArrayList<Integer> S=new ArrayList<>();
			for (int i = 0; i < e[A].size(); i++) {
				S.add(e[A].get(i));
			}
			g.delete_vertice(A);
			Pair p1 = ms2(g, S);


			return pair_bigger(p1, p2);
		}
		ArrayList<Integer> a=new ArrayList<>();
		ArrayList<Integer> b=new ArrayList<>();
		a.add(A);
		b.add(B);
		ArrayList<Integer> NA=union(e[A],a);
		ArrayList<Integer> NB=union(e[B],b);
		if (is_subset(NA, NB)) {
			g.delete_vertice(B);
			Pair p = ms(g);
			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;
		return pair_bigger(p1, 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;
		else if (S.size() == 2) {
			int u = S.get(0);
			int v = S.get(1);
			if (edge(u,v,e))
				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;
			}
		} else 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_vertice(s[0]);
				S.remove((Integer) s[0]);
				p = ms1(g, S);
				p.cardinality++;
				p.choosed_vertices[s[0]] = true;
				return p;
			} else if (edge(s[0], s[1], e) && edge(s[1], s[2], e) && edge(s[2], s[0], e)) {
				return p;
			}
			for (int i = 0; i < 3; i++) {
				int u = s[(i + 1) % 3];
				int v = s[(i + 2) % 3];

				if (edge(u, s[i], e) && edge(s[i], v, e)) {
					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 (edge(u, v, e)) {
					g.delete_v_with_neighbours(s[i]);
					S.remove((Integer) s[i]);
					p = ms1(g, S);
					p.cardinality++;
					p.choosed_vertices[s[i]] = true;
					return p;
				}
			}

			for (int i = 0; i < 3; i++) {
				int u = s[i];
				int v = s[(i + 1) % 3];
				ArrayList<Integer> intersection = intersection(e[u], e[v]);
				if (intersection.size() >= 1) {
					int w = intersection.get(0);
					g.delete_vertice(w);
					p = ms2(g, S);
					return p;
				}
			}
			if (deg[s[0]] == 1) {
				g.delete_v_with_neighbours(s[0]);
				S.remove((Integer) s[0]);
				p = ms1(g, S);
				p.cardinality++;
				p.choosed_vertices[s[0]] = true;
				return p;
			} else {

				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]);
				ArrayList<Integer> S2 = new ArrayList<>();
				for (int i = 0; i < e[s[0]].size(); i++) {
					S2.add(e[s[0]].get(i));
				}
				g.delete_vertice(s[0]);
				Pair p2=ms(g);
				//				Pair p2 = ms2(g,S2);
				p2.cardinality+=2;
				p2.choosed_vertices[s[2]]=true;
				p2.choosed_vertices[s[1]]=true;

				return pair_bigger(p, p2);
			}
		}
		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);
				return pair_bigger(p, p2);
			}
		}
		if (S.size() <= 4)
			throw new AssertionError();
		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;

		for(int i=0;i<S.size();i++){
			int v=S.get(i);
			if(!valid_vertices[v]){
				throw new AssertionError();
			}
		}

		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 (deg[s1] <= 1) {
			return ms(g);
		} else if (edge(s1,s2,e)) {
			if (deg[s1] <= 3)
				return ms(g);
			else {
				Graph g2 = g.copy();

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

				g2.delete_v_with_neighbours(s2);
				Pair p2 = ms(g2);
				p2.cardinality++;
				p2.choosed_vertices[s2] = true;
				return pair_bigger(p1, p2);
			}
		}
		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 (deg[s1] != 2) {
				throw new AssertionError("deg[s1]!=2");
			}
			int E = e[s1].get(0);
			int F = e[s1].get(1);
			if (edge(E,F,e)) {
				g.delete_v_with_neighbours(s1);
				Pair p = ms(g);
				p.cardinality++;
				p.choosed_vertices[s1] = true;
				return p;
			}
			ArrayList<Integer> union = union(e[E], e[F]);
			union.remove((Integer) s1);
			if (is_subset(union, e[s2])) {
				g.delete_v_with_neighbours(E);
				g.delete_v_with_neighbours(F);
				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(E);
				g.delete_v_with_neighbours(F);
				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;

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

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

			g2.delete_v_with_neighbours(s1);
			ArrayList<Integer> S2=new ArrayList<>();
			for(int i=0;i<e[s2].size();i++){
				S2.add(e[s2].get(i));
			}
			g2.delete_vertice(s2);
			Pair p2 = ms2(g2, S2);
			p2.cardinality++;
			p2.choosed_vertices[s1] = true;

			p = pair_bigger(p, p2);
			return p;
		}

	}

	class Pair {
		int cardinality;
		boolean[] choosed_vertices;

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

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


	// 頂点u,v間に辺が存在するときtrueを返す。
	boolean edge(int u, int v, ArrayList<Integer>[] e) {
		if (e[u].contains(v))
			return true;
		else
			return false;
	}

	@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;
	}
	Pair pair_union(Pair p1,Pair p2){
		int n=p1.choosed_vertices.length;
		int cardinality=0;

		boolean[] d=new boolean[n];
		for(int i=0;i<n;i++){
			if(p1.choosed_vertices[i]&&p2.choosed_vertices[i]){
				throw new AssertionError();
			}
			if(p1.choosed_vertices[i]||p2.choosed_vertices[i]){
				d[i]=true;
				cardinality++;
			}
		}
		return new Pair(cardinality,d);
	}
	class DJSet{
		int n;//the number of vertices
		int[] d;
		DJSet(int n){
			this.n=n;
			d=new int[n];
			Arrays.fill(d, -1);
		}
		int root(int x){
			return d[x]<0?x:root(d[x]);
		}
		boolean setUnion(int x,int y){
			x=root(x);
			y=root(y);
			if(x!=y){
				if(x<y){
					int d=x;
					x=y;
					y=d;
				}
				//x>y
				d[y]+=d[x];
				d[x]=y;
			}
			return x!=y;
		}
		boolean equiv(int x,int y){
			return root(x)==root(y);
		}
		//xを含む木のNodeの数
		int size(int x){
			return d[root(x)]*(-1);
		}
		//連結グラフの数
		int count(){
			int ct=0;
			for(int u:d){
				if(u<0)ct++;
			}
			return ct;
		}
	}
	void tr(Object...o){System.out.println(Arrays.deepToString(o));}
}
0