思路:设置两个游标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)的求法我还不是搞的很懂,有空值得研究一下。

原文点此索引目录。感谢xiazdong君
&& Google酱。这里是偶尔做做搬运工的水果君(^_^)

《算法导论》习题解答 Chapter 22.1-6(求universal sink 通用汇点)的更多相关文章

  1. 《算法导论》习题解答 Chapter 22.1-5(求平方图)

    一.邻接矩阵实现 思路:如果是邻接矩阵存储,设邻接矩阵为A,则A*A即为平方图,只需要矩阵相乘即可: 伪代码: for i=1 to n for j=1 to n for k=1 to n resul ...

  2. (搬运)《算法导论》习题解答 Chapter 22.1-1(入度和出度)

    (搬运)<算法导论>习题解答 Chapter 22.1-1(入度和出度) 思路:遍历邻接列表即可; 伪代码: for u 属于 Vertex for v属于 Adj[u] outdegre ...

  3. 《算法导论》习题解答 Chapter 22.1-4(去除重边)

    思路:重开一个新图,按着邻接列表的顺序从上到下遍历,每遍历一行链表前,清空visited数组,如果没有访问过这个元素,则加入新图,如果已经访问过了(重边),则不动. 伪代码: 复杂度:O(V+E) f ...

  4. 《算法导论》习题解答 Chapter 22.1-8(变换邻接表的数据结构)

    一般散列表都与B+树进行比较,包括在信息检索中也是. 确定某条边是否存在需要O(1). 不足: (1)散列冲突. (2)哈希函数需要不断变化以适应需求. 另外:B+树.(见第18章) 与散列表相比的不 ...

  5. 《算法导论》习题解答 Chapter 22.1-7(关联矩阵的性质)

    主对角线:出度+入度 其他:arr[i][j]=-n,则i与j之间有n条边. 证明: (原文点此,索引目录.感谢xiazdong君 && Google酱.这里是偶尔做做搬运工的水果君( ...

  6. 《算法导论》习题解答 Chapter 22.1-3(转置图)

    一.邻接表实现 思路:一边遍历,一边倒置边,并添加到新的图中 邻接表实现伪代码: for each u 属于 Vertex for v 属于 Adj[u] Adj1[v].insert(u); 复杂度 ...

  7. 《算法导论》习题解答 Chapter 22.1-2(邻接矩阵与链表)

    链表如图: 矩阵: 1 2 3 4 5 6 7 1 0 1 1 0 0 0 0 2 1 0 0 1 1 0 0 3 1 0 0 0 0 1 1 4 0 1 0 0 0 0 0 5 0 1 0 0 0 ...

  8. C++ Primer(第五版)读书笔记 & 习题解答 --- Chapter 3

    Chapter 3.1 1. using声明具有如下的形式: using namespace::name; Chapter 3.2 1. C++标准一方面对库类型所提供的操作做了规定,另一方面也对库的 ...

  9. C++ Primer(第五版)读书笔记 & 习题解答 --- Chapter 2

    Chapter 2.1 1. 数据类型决定了程序中数据和操作的意义. 2. C++定义了一套基本数据类型,其中包括算术类型和一个名为void的特殊类型.算术类型包含了字符.整型.布尔值以及浮点数.vo ...

随机推荐

  1. How Tomcat Works(六)

    本文继续分析HttpProcessor类,该类实现了org.apache.catalina.Lifecycle接口和java.lang.Runnable接口 我们先分析它的构造函数 /** * The ...

  2. OpenSSL命令---ciphers

    用途: 指令是用来展示用于SSL加密算法的工具.它能够把所有openssl支持的加密算法按照一定规律排列(一般是加密强度).这样可以用来做测试工具,决定使用什么加密算法. 用法: openssl ci ...

  3. 三种JDBC批量插入编程方法的比较

    JDBC批量插入主要用于数据导入和日志记录因为日志一般都是先写在文件下的等. 我用Mysql 5.1.5的JDBC driver 分别对三种比较常用的方法做了测试 方法一,使用PreparedStat ...

  4. C#扫描仪编程、条形码识别编程资料

    扫描仪编程资料:http://www.cnblogs.com/wubh/archive/2011/11/07/2239178.html 图片条形码识别资料:http://www.codeproject ...

  5. sql 分组后 组内排名

    语法:ROW_NUMBER() OVER(PARTITION BY COLUMN ORDER BY COLUMN) 简单的说row_number()从1开始,为每一条分组记录返回一个数字,这里的ROW ...

  6. [转]iOS应用性能调优的25个建议和技巧

    写在前面 本文来自iOS Tutorial Team 的 Marcelo Fabri,他是Movile的一名 iOS 程序员.这是他的个人网站:http://www.marcelofabri.com/ ...

  7. bzoj 1041: [HAOI2008]圆上的整点 数学

    1041: [HAOI2008]圆上的整点 Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeOnline/ ...

  8. js密码强度

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  9. 几种更新(Update语句)查询的方法

    正 文: 数据库更新就一种方法Update,其标准格式:Update 表名 set 字段=值 where 条件只是依据数据的来源不同,还是有所差别的:  1.从外部输入这样的比較简单例:update ...

  10. [Angular 2] Generate Angular 2 Components Programmatically with entryComponents & ViewContainerRef

    You can generate Angular 2 components using a combination of ViewContainer and ComponentFactory, but ...