《演算法導論》習題解答 Chapter 22.1-6(求universal sink 通用匯點)
阿新 • • 發佈:2019-02-13
思路:設定兩個遊標i指向行,j指向列,如果arr[i][j]==1,則i=max{i+1,j},j++;如果arr[i][j]==0,則j=max{i+1,j+1}。
虛擬碼:
has_universal_sink() for i=1 to N //對角線檢查是否全是0 if A[i][i]==1 return false; i=1,j=2 while(i<=N && j<=N) if(A[i][j]==1) i=max{i+1,j} j++ else j=max{i+1,j+1} if i<=N if check arr[i][*]=0,arr[*(except i)][i]=1 return true; else return false; else return false;
命題:如果A[i][j]=0,則j不是通用匯點。
因為A[i][j]=0,說明i到j沒有邊,而通用匯點的定義是一定要每個點都要有一條指向他的邊,因此j不是通用匯點。
命題:如果A[i][j]=1,則i不是通用匯點。
因為A[i][j]=1,所以i到j有一條邊,所以i不是通用匯點。
迴圈不變式:每次迭代前,i之前和j之前但不包括i的點都不是通用匯點。
初始:i=1,j=2,i之前為空,j之前但不包括i的點也為空,因此成立。
保持:在迭代開始時,已知i之前和j之前但不包括i的點都不是通用匯點,當進入迴圈體後,如果A[i][j]==1,則說明i肯定不是通用匯點,並且已知j之前不包括i的點不是通用匯點,因此i=max{i+1,j},j++後仍然保持不變式;如果A[i][j]==0,則j不是通用匯點,如果j原本小於i,則j要到i+1,因為已知i之前的點肯定不是通用匯點,所以現在仍然保持不變式成立。
終止:如果i<=N,j=N+1,j之前除了i其他點都不是通用匯點,因此需要去全面檢查i是不是通用匯點。如果i=N+1,則不需要檢查了,沒有通用匯點。
命題:如果A[i][j]=1,則j之前的點都不是通用匯點。
命題:如果A[i][j]=0,則i之前的點都不是通用匯點。
輸入:
4 3
a c
b c
d c
原始碼:
package C22; import java.io.ObjectInputStream.GetField; /** * 此處提供兩種方法,一種是網上的方法,一種是自己想的方法, * 經過測試,如果同時執行100000000次,則網上的方法速度是3.6秒,我的方法速度是3秒 * @author xiazdong * */ public class C1_6 { private static int sink_index = -1; public static void main(String[] args) throws Exception { Adjacent_Matrix adj_matrix = GraphFactory.getAdjacentMatrixInstance("input\\22.1-6.txt"); boolean flag = has_universal_sink(adj_matrix); if(flag)System.out.println(adj_matrix.getVertexValue(sink_index)); } /** * 自己的方法 * @return */ public static boolean has_universal_sink(Adjacent_Matrix g){ int i=0,j=0; boolean flag = true; while(j<=g.getSize()-1){ if(g.getElement(i, j)==1){ i = j; } j++; } //檢查arr[i][*]==0 arr[*(except i)][i]==1 for(int a=0;a<g.getSize();a++){ if(g.getElement(i, a)==1&&i!=a){ flag = false; } if(g.getElement(a, i)==0&&i!=a){ flag = false; } } if(flag) sink_index = i; return flag; } /** * 網上的方法 * @return */ public static boolean has_universal_sink2(Adjacent_Matrix g){ int i=0,j=0; boolean flag = true; while(j<=g.getSize()-1){ if(g.getElement(i, j)==1){ i++; } else j++; } //檢查arr[i][*]==0 arr[*(except i)][i]==1 for(int a=0;a<g.getSize();a++){ if(g.getElement(i, a)==1&&i!=a){ flag = false; } if(g.getElement(a, i)==0&&i!=a){ flag = false; } } if(flag) sink_index = i; return flag; } }
這邊還有一篇跟通用匯點有關的博文,說實話,通用匯點的o(v)的求法我還不是搞的很懂,有空值得研究一下。