还记得上次小Hi和小Ho学校被黑客攻击的事情么,那一次攻击最后造成了学校网络数据的丢失。为了避免再次出现这样的情况,学校决定对校园网络进行重新设计。
学校现在一共拥有N台服务器(编号1..N)以及M条连接,保证了任意两台服务器之间都能够通过连接直接或者间接的数据通讯。
当发生黑客攻击时,学校会立刻切断网络中的一条连接或是立刻关闭一台服务器,使得整个网络被隔离成两个独立的部分。
举个例子,对于以下的网络:
每两个点之间至少有一条路径连通,当切断边(3,4)的时候,可以发现,整个网络被隔离为{1,2,3},{4,5,6}两个部分:
若关闭服务器3,则整个网络被隔离为{1,2},{4,5,6}两个部分:
小Hi和小Ho想要知道,在学校的网络中有哪些连接和哪些点被关闭后,能够使得整个网络被隔离为两个部分。
在上面的例子中,满足条件的有边(3,4),点3和点4。
第1行:2个正整数,N,M。表示点的数量N,边的数量M。1≤N≤20,000, 1≤M≤100,000
第2..M+1行:2个正整数,u,v。表示存在一条边(u,v),连接了u,v两台服务器。1≤u<v≤N
保证输入所有点之间至少有一条连通路径。
第1行:若干整数,用空格隔开,表示满足要求的服务器编号。从小到大排列。若没有满足要求的点,该行输出Null
第2..k行:每行2个整数,(u,v)表示满足要求的边,u<v。所有边根据u的大小排序,u小的排在前,当u相同时,v小的排在前面。若没有满足要求的边,则不输出
6 7 1 2 1 3 2 3 3 4 4 5 4 6 5 6
3 4 3 4
1 import java.util.ArrayList; 2 import java.util.HashSet; 3 import java.util.Scanner; 4 import java.util.Set; 5 import java.util.Stack; 6 import java.util.TreeSet; 7 8 9 10 public class Main { 11 12 static int N_Max=0; //记录根节点是否有两个或多个子树 13 static int NUM=0; //记录已经遍历的个数 14 static int [] checktable; 15 static int [] havechecktable; 16 static Stack<Integer> stack=new Stack(); 17 public static void main(String[] argv){ 18 Scanner in = new Scanner(System.in); 19 int N = in.nextInt(); 20 int M = in.nextInt(); 21 checktable= new int[N]; //记录遍历顺序 22 havechecktable= new int[N]; //记录是否已经遍历的标示 23 int[] y_min= new int[N]; //记录非树边所能达到的小次序值 24 int[] min = new int[N]; //记录Low值 25 int[] sort_check = new int[N];//记录每个id点的遍历次序 26 ArrayList<Integer> [] source = new ArrayList[N]; //记录图的矩阵 27 ArrayList<Integer> [] blue = new ArrayList[N]; //记录遍历树的矩阵 28 Set<String> out_xian = new HashSet<String>(); 29 Set<Integer> out_dian = new HashSet<Integer>(); 30 ArrayList<Integer> [] out_xian_2 = new ArrayList[N]; 31 int[][] xian_resource = new int[N][N]; 32 //ArrayList<Integer> out_dian = new ArrayList<Integer>(); 33 //ArrayList out_xian = new ArrayList(); 34 //初始化矩阵 35 for(int i=0; i<N; i++){ 36 source[i] = new ArrayList<Integer>(); 37 blue[i] = new ArrayList<Integer>(); 38 out_xian_2[i] = new ArrayList<Integer>(); 39 } 40 /************************记录矩阵**********************/ 41 for(int i=0; i<M; i++){ 42 int x=in.nextInt()-1; int y= in.nextInt()-1; 43 source[x].add(y); 44 source[y].add(x); 45 } 46 /************************深度遍历**********************/ 47 dfn(source, checktable, blue); 48 49 /************************验证非树边**********************/ 50 /* 51 //System.out.println("BLUE: "); 52 for(int i=0; i<N; i++){ 53 54 System.out.println(" "+blue[i].toString()); 55 } 56 */ 57 /************************get sort_check[](即 dfn[])**********************/ 58 for(int i=0; i<N; i++){ 59 source[i].removeAll(blue[i]); 60 sort_check[checktable[i]]=i; 61 } 62 /************************验证dfn[] and y_min[]**********************/ 63 /* 64 System.out.println("Sort_Check: "); 65 for(int i=0; i<N; i++){ 66 System.out.println(" "+sort_check[i]); 67 } 68 System.out.println("YELLOW: "); 69 for(int i=0; i<N; i++){ 70 System.out.println(source[i].toString()); 71 } 72 */ 73 /************************Get the y_low[]**********************/ 74 //System.out.println("YELLOW_min: "); 75 for(int i=0; i<N; i++){ 76 int ymin=i; 77 for(Object k: source[checktable[i]]){ 78 int spit = sort_check[(int)k]; 79 if(spit<ymin) 80 ymin=spit; 81 } 82 //System.out.print(" "+ymin); 83 y_min[i]=ymin; 84 } 85 /************************Get the low[]**********************/ 86 //System.out.println(); 87 //System.out.println("Low: "); 88 for(int i=N-1; i>=0; i--){ 89 int k_low = checktable[i]; 90 min[i]=y_min[i]; 91 for(Object o_int : blue[k_low] ){ 92 93 if(sort_check[k_low]<sort_check[(int)o_int]){ 94 95 if(min[i]>min[sort_check[(int)o_int]]) 96 min[i]=min[sort_check[(int)o_int]]; 97 } 98 } 99 // Low[] 100 //System.out.println(" "+i+" "+k_low+": "+min[i]); 101 } 102 /************************Get result**********************/ 103 for(int i=0; i<N; i++){ 104 105 for(Object blue_k : blue[i]){ 106 107 //System.out.println(i+": "+min[sort_check[(int)blue_k]]+">="+sort_check[i]); 108 if(min[sort_check[(int)blue_k]]>=sort_check[i]){ 109 //System.out.println(i+" added. "); 110 if(i>0) 111 out_dian.add(i+1); 112 if(min[sort_check[(int)blue_k]]>sort_check[i]){ 113 //String temp = ""; 114 int x=i+1; 115 int y=(int)blue_k+1; 116 if(i<(int)blue_k){ 117 //temp=x+" "+y; 118 out_xian_2[i].add((int)blue_k); 119 } 120 else{ 121 //temp=y+" "+x; 122 out_xian_2[(int)blue_k].add(i); 123 } 124 125 126 } 127 } 128 } 129 } 130 if(N_Max>1) 131 out_dian.add(1); 132 //System.out.println(out_dian.toString()); 133 /************************Output result**********************/ 134 java.util.Iterator<Integer> it_dian=out_dian.iterator(); 135 //java.util.Iterator<String> it_xian=out_xian.iterator(); 136 int[] dian_sqit_list = new int[N+1]; 137 String dian_result=""; 138 while(it_dian.hasNext()) 139 { 140 dian_sqit_list[it_dian.next()]=1; 141 //dian_result=dian_result+it_dian.next()+" "; 142 } 143 for(int i=1; i<=N; i++){ 144 if(dian_sqit_list[i]==1) 145 dian_result=dian_result+i+" "; 146 } 147 //System.out.println("::::::"+dian_result); 148 if(dian_result.length()>1){ 149 dian_result=dian_result.substring(0,dian_result.length()-1); 150 System.out.println(dian_result); 151 } 152 else 153 System.out.println("Null"); 154 155 for(int i=0; i<N; i++){ 156 157 int[] out_xian_temp = new int[N]; 158 for(int out_m : out_xian_2[i]){ 159 160 out_xian_temp[out_m]=1; 161 162 } 163 for(int j=0; j<N;j++ ){ 164 165 if(out_xian_temp[j]==1){ 166 System.out.print(i+1); 167 System.out.print(" "); 168 System.out.println(j+1); 169 } 170 171 172 } 173 174 } 175 176 /* 177 while(it_xian.hasNext()) 178 { 179 System.out.println(it_xian.next()); 180 } 181 */ 182 } 183 184 public static void dfn(ArrayList[] source, int[] checktable, ArrayList[] blue){ 185 186 //int size = source.length; 187 int start =0; 188 checktable[NUM++]=start; 189 havechecktable[start]=1; 190 stack.push(start); 191 while(true){ 192 193 int end = Had(source[start],start,checktable,havechecktable); 194 if(end>=0){ 195 if(start==0) 196 N_Max++; 197 blue[start].add(end); 198 blue[end].add(start); 199 //System.out.println(end); 200 stack.push(end); 201 //stack.push(start); 202 //start = end; 203 //System.out.println("start:"+start+" end"+end+" "+"NUM:"+NUM); 204 checktable[NUM++]=end; 205 havechecktable[end]=1; 206 } 207 else{ 208 209 stack.pop(); 210 } 211 if(stack.isEmpty()) 212 break; 213 else{ 214 start=stack.pop(); 215 stack.push(start); 216 } 217 218 219 } 220 //System.out.println(N_Max); 221 222 } 223 224 public static int Had(ArrayList s_source, int s_check, int[] check_table, int[] havechecked){ 225 226 for(int i=0; i<s_source.size();i++){ 227 //System.out.println(s_source.toString()); 228 int key = (int)s_source.get(i); 229 //System.out.println(key); 230 if(havechecked[key]==0){ 231 return key; 232 } 233 } 234 235 return -1; 236 } 237 }