結果
問題 | No.382 シャイな人たち (2) |
ユーザー | 37zigen |
提出日時 | 2016-06-26 15:48:00 |
言語 | Java21 (openjdk 21) |
結果 |
TLE
|
実行時間 | - |
コード長 | 16,886 bytes |
コンパイル時間 | 3,077 ms |
コンパイル使用メモリ | 94,280 KB |
実行使用メモリ | 67,024 KB |
最終ジャッジ日時 | 2024-10-11 23:26:32 |
合計ジャッジ時間 | 21,693 ms |
ジャッジサーバーID (参考情報) |
judge4 / judge5 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
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 | -- | - |
ソースコード
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));} }