算法概论实验十 发表于 2019-03-14 | 分类于 算法概论实验 1234567891011实验十实验目的与要求:(1) 掌握使用图的深度优先搜索算法实现对有向图中是否包含环的判断;(2) 掌握使用图的深度优先搜索算法实现对有向图的强连通分量的划分。1.有向图中环的判断问题【问题描述】给定一个有向图,要求使用深度优先搜索策略,判断图中是否存在环。2.有向图的强连通分量问题【问题描述】给定一个有向图,设计一个算法,求解并输出该图的各个强连通分量。 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186import java.util.ArrayList;public class exam10 { //1.有向图判环 public static String havecycle(int[][] a) { if(DFS(a)) //如果没环 return "no cycle"; else return "have cycle"; } public static boolean DFS(int[][] a) //有环返回false { boolean test = true; int length = a.length; String[] color = new String[length]; for(int i=0;i<length;i++) color[i] = "white"; //int clock = 1; for(int i=0;i<length;i++) if(color[i] == "white") { test = explore(a,i,color); if(test == false) return false; } return true; } public static boolean explore (int[][] a,int u,String[] color) //以u为顶点进行探索 { color[u] = "gray"; for(int v=0;v<a.length;v++) { if(a[u][v]!=0 && color[v]=="white") explore(a,v,color); if(a[u][v]!=0 && color[v]=="gray") //如果有一条回边,表示有一个环 return false; } color[u] = "black"; return true; } //2.找强连通分量 public static void findSC(int[][] a1) { int length = a1.length; int[][] a = new int[length][length]; int[][] b = new int[length][length]; getGR(a1,b); //b是反向图 getGR(b,a); //防止修改原图a=a1 Set[] set = new Set[length]; int count = 0; int sum = 0; //要在反向图中找一个Post值最大的点,以这个点为起点,在原图上进行DFS,则找到一个强连通部件 do { System.out.print("第"+(count+1)+"个连通分量为:"); getGR(a,b); int maxpost = findmaxpost(b); set[count] = DFS2(a,maxpost); //第一个强连通部件set[0] //去掉这个连通部件中的点 for(int i=0;i<set[count].value.size();i++) { int p = set[count].value.indexOf(i); delete(a,p); } sum = sum + set[count].value.size(); //sum计算去掉的点数 count++; System.out.println(); }while(sum<length); } //在一个图中找出post值最大的节点点 public static int findmaxpost(int[][] a) { int max = 0; int maxindex = 0; int[] post = new int[a.length]; DFS1(a,post); for(int i=0;i<a.length;i++) { int temp = max; max = Math.max(max, post[i]); if(max != temp) maxindex = i; } return maxindex; } public static void DFS1(int[][] a,int[] post) { int length = a.length; String[] color = new String[length]; for(int i=0;i<length;i++) color[i] = "white"; int[] clock = new int[1]; clock[0] = 1; for(int i=0;i<length;i++) if(color[i] == "white") { explore1(a,i,color,post,clock); } } public static void explore1 (int[][] a,int u,String[] color,int[] post,int[] clock)//以u为顶点进行探索 { color[u] = "gray"; clock[0]++; for(int v=0;v<a.length;v++) { if(a[u][v]!=0 && color[v]=="white") explore1(a,v,color,post,clock); } color[u] = "black"; post[u] = clock[0]; //System.out.print("post["+u+"]="+post[u]+" "); clock[0]++; } //获得一个图的反向图 public static void getGR(int[][] a,int[][] b) { for(int i=0;i<a.length;i++) for(int j=0;j<a.length;j++) b[i][j] = a[j][i]; } //返回u能访问到的点集 public static Set DFS2(int[][] a,int u) { Set s = new Set(); int length = a.length; String[] color = new String[length]; for(int i=0;i<length;i++) color[i] = "white"; //初始化完成 explore2(a,u,color,s); return s; } public static void explore2(int[][] a,int u,String[] color,Set s)//以u为顶点进行探索 { s.value.add(u); System.out.print(u+" "); color[u] = "gray"; for(int v=0;v<a.length;v++) { if(a[u][v]!=0 && color[v]=="white") explore2(a,v,color,s); } color[u] = "black"; } //删除a中所有与p相连的边 public static void delete(int[][] a,int p) { for(int i=0;i<a.length;i++) { a[i][p] = 0; a[p][i] = 0; } } public static void main(String[] args) { //测环 int[][] a = new int[6][6]; for(int i=0;i<a.length;i++) for(int j=0;j<a.length;j++) a[i][j] = 0; a[1][0] = 1;a[1][3] = 1;a[2][1] = 1;a[3][4] = 1; a[4][5] = 1;a[5][2] = 1;a[5][3] = 1; System.out.println(havecycle(a)); //强连通分量 findSC(a); }}