Ex3_15 判断图是否是一个强连通分量 判断点是否在汇点强连通分量中_十一次作业

(a) 可以用图中的每一个顶点表示街道中的每个十字路口,由于街道都是单行的,所以图是有向图,若从一个十字路口都有一条合法的路线到另一个十字路口,则图是一个强连通图。即要验证的是图是否是一个强连通图。
(b) 若从市政厅沿着合法路线到达任何一个地方都有合法路线返回则说明市政厅位于一个有向图中的一个汇点强连通部件中。
package org.xiu68.ch03.ex11; import java.util.ArrayList;
import java.util.List;
import java.util.Stack; public class Ex3_15 { public static void main(String[] args) {
// TODO Auto-generated method stub
int[][] edges=new int[][]{
{0,1,0,0},
{0,0,1,0},
{0,0,0,1},
{1,0,0,0}
};
MGraph1 m1=new MGraph1(edges);
m1.checkSC(0); //强连通图 System.out.println("***************************");
int[][] edges1=new int[][]{
{0,1,0,1},
{0,0,1,0},
{0,0,0,1},
{0,0,0,0}
};
MGraph1 m2=new MGraph1(edges1);
m2.checkSC(0);
for(int i=0;i<4;i++){
System.out.print(i+":");
m2.isInSinkSCC(i);
}
//输出
/*
非强连通图
0:不存在汇点强连通分量中
1:不存在汇点强连通分量中
2:不存在汇点强连通分量中
3:存在汇点强连通分量中
*/ System.out.println("***************************");
int[][] edges3=new int[][]{
{0,0,0,0,0,0,0},
{1,0,0,1,0,0,0},
{1,0,0,1,0,0,0},
{0,0,0,0,1,1,0},
{0,0,0,1,0,0,1},
{0,0,0,1,0,0,1},
{0,0,0,0,1,1,0}
};
MGraph1 m3=new MGraph1(edges3);
for(int i=0;i<edges3.length;i++){
System.out.print(i+":");
m3.isInSinkSCC(i);
}
//输出
/*
0:存在汇点强连通分量中
1:不存在汇点强连通分量中
2:不存在汇点强连通分量中
3:存在汇点强连通分量中
4:存在汇点强连通分量中
5:存在汇点强连通分量中
6:存在汇点强连通分量中
*/
} } class MGraph1{
private int[][] edges; //有向图
private int[][] rEdges; //有向图的反向图
private int vexNum; //顶点数量
private Stack<Integer> stack; //存储反向图深度优先遍历的post值 public MGraph1(int[][] edges){
this.edges=edges;
this.vexNum=edges.length;
stack=new Stack<>();
rEdges=new int[vexNum][vexNum]; //反向图 //求原图的反向图
for(int i=0;i<vexNum;i++){
for(int j=i+1;j<vexNum;j++){
rEdges[i][j]=edges[j][i];
rEdges[j][i]=edges[i][j];
}
} }
//******************************************************
//验证图是否是强连通的
/*
* 先从某个顶点开始对原图进行深度优先遍历
* 再从这个顶点开始对反向图做深度优先遍历
* 若两次遍历都能访问所有顶点说明是强连通图
*/
public void checkSC(int v){
boolean[] visited=new boolean[vexNum]; //原图中已访问的顶点
dfs(edges,visited,v); boolean[] rVisited=new boolean[vexNum]; //反向图中已访问的顶点
dfs(rEdges,rVisited,v); for(int i=0;i<vexNum;i++){
if(!visited[i] || !rVisited[i]){
System.out.println("非强连通图");
return;
}
}
System.out.println("强连通图");
} //深度优先遍历
public void dfs(int[][] edges,boolean[] visited,int v){
visited[v]=true;
for(int i=0;i<vexNum;i++){
if(edges[v][i]==1 && !visited[i]){
dfs(edges,visited,i);
}
}
}
//**************************************************************
//判断一个顶点是否位于一个汇点强连通部件中
public void isInSinkSCC(int target){
rDFSTraverse(); //先对反向图进行深度优先遍历 //List<List<Integer>> sccs=new ArrayList<>(); //存放每一个强连通部件对应的顶点 boolean[] visited=new boolean[vexNum]; //记录深度优先遍历原图过程中非当前强连通分量已经访问的顶点
int[] visitedN=new int[vexNum]; //记录顶点属于第几个强连通分量
boolean[] isSinkSCC=new boolean[vexNum]; //记录第i个强连通分量是否是汇点强连通部件,最多有vexNum个强连通部件
int n=0; //第几个强连通部件 for(int i=0;i<vexNum;i++){
visitedN[i]=-1;
isSinkSCC[i]=true;
} while(!stack.isEmpty()){
int v=stack.pop();
if(!visited[v]){
//sccs.add(new ArrayList<Integer>());
List<Integer> vexs=new ArrayList<>(); //记录第n个强连通分量的顶点 DFS(visited,visitedN,v,vexs,isSinkSCC,n);
for(int i=0;i<vexs.size();i++){
//sccs.get(i).add(vexs.get(i));
visited[vexs.get(i)]=true;
}
n++;
}
}
if(isSinkSCC[visitedN[target]]){
System.out.println("存在汇点强连通分量中");
}else{
System.out.println("不存在汇点强连通分量中");
}
}
/*
* 对原图进行深度优先遍历
* 在汇点强连通部件中对某个顶点进行深度优先遍历则刚好访问该强连通部件的所有顶点
*/
private void DFS(boolean[] visited,int[] visitedN,int v,/*List<List<Integer>> sccs,*/
List<Integer> vexs,boolean[] isSinkSCC,int n){
//sccs.get(n).add(v);
vexs.add(v);
visitedN[v]=n;
for(int i=0;i<vexNum;i++){
if(edges[v][i]==1){
//若在一个汇点强连通部件中进行深度优先遍历,刚好得到该汇点强连通部件
//若遍历到其他强连通分量的顶点说明该强连通分量不是汇点强连通分量
if(visited[i]){
isSinkSCC[n]=false;
}else if(visitedN[i]!=n){
DFS(visited,visitedN,i,/*sccs,*/vexs,isSinkSCC,n);
}
}
}//for
} //**************************************************************
/*
* 对反向图进行深度优先遍历,post值最大的顶点将位于反向图中的一个源点强连通部件,
* 也就是原图中的某个汇点连通部件的某个顶点
* 按post值从小到大,压入栈中
*/
public void rDFSTraverse(){
boolean[] visited=new boolean[vexNum];
for(int i=0;i<vexNum;i++){
if(!visited[i]){
rDFS(visited,stack,i);
}
}
}
//对反向图做深度优先遍历
private void rDFS(boolean[] visited,Stack<Integer> stack,int v){
visited[v]=true;
for(int i=0;i<vexNum;i++){
if(rEdges[v][i]==1 && !visited[i]){
rDFS(visited,stack,i);
}
}
stack.push(v);
}
}
Ex3_15 判断图是否是一个强连通分量 判断点是否在汇点强连通分量中_十一次作业的更多相关文章
- Ex 3_25 图中每个顶点有一个相关价格..._十一次作业
(a)首先对有向无环图进行拓扑排序,再按拓扑排序的逆序依次计算每个顶点的cost值,每个顶点的cost值为自身的price值与相邻顶点间的cost值得最小值 (b)求出图中的每一个强连通分量,并把所有 ...
- ViewPager 滑动一半的判断方法以及左滑右滑判断
做项目的时候,会碰到用viewpager + fragments去实现多页滑动.有些时候需要完成:界面在滑动到一半或是一半以上的时候,需要把title之类的切换到下一个页面.这个时候仅仅依赖Viewp ...
- POJ 1860 Currency Exchange(如何Bellman-Ford算法判断图中是否存在正环)
题目链接: https://cn.vjudge.net/problem/POJ-1860 Several currency exchange points are working in our cit ...
- 判断图连通的三种方法——dfs,bfs,并查集
Description 如果无向图G每对顶点v和w都有从v到w的路径,那么称无向图G是连通的.现在给定一张无向图,判断它是否是连通的. Input 第一行有2个整数n和m(0 < n,m < ...
- POJ_1064_Cable_master_(二分,假定一个解并判断是否可行)
描述 http://poj.org/problem?id=1064 有n条绳子,长度分别为l[i].如果从它们中切割出k条长度相同的绳子的话,这k条绳子每条最长能有多少? Cable master T ...
- 金牌分析师助力 鲁泰A图谋再造一个“鲁泰”?_财经_中国网
金牌分析师助力 鲁泰A图谋再造一个"鲁泰"?_财经_中国网 金牌分析师助力 鲁泰A图谋再造一个"鲁泰"?
- 《剑指Offer》第1题(Java实现):在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
一.题目描述 在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序.请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该 ...
- Github作为图床的一个小坑
Github作为图床的一个小坑 前言 听了少铭同学建议把github作为图床,结果遇到了一个小坑,总是显示不出来图片. 问题描述与解决 形如下的链接是显示不出来的: https://github.co ...
- HDU-1232 畅通工程 (并查集、判断图中树的棵数)
Description 某省调查城镇交通状况,得到现有城镇道路统计表,表中列出了每条道路直接连通的城镇.省政府“畅通工程”的目标是使全省任何两个城镇间都可以实现交通(但不一定有直接的道路相连,只要互相 ...
随机推荐
- P1382 楼房 set用法小结
这个sb题目,剧毒... STL大法好 首先,我准备用经典的线段树优化扫描线来做.之前的矩形周长把我困了数天导致我胸有成竹. 然后,敲代码半小时,调试半个月......这个,sb,怎么改都是0分+2个 ...
- sizeof 与 字节对齐
转:http://baike.baidu.com/view/1356720.htm sizeof是运算符,可用于任何变量名.类型名或常量值,当用于变量名(不是数组名)或常量时,它不需要用圆括号. ...
- 串口、COM口、TTL、RS-232、RS-485区别详解
1.串口.COM口是指的物理接口形式(硬件).而TTL.RS-232.RS-485是指的电平标准(电信号). 2.接设备的时候,一般只接GND RX TX.不会接Vcc或者+3.3v的电源线,避 ...
- java基础基础总结----- 关键字、标识符、注释、常量和变量、运算符、语句、函数、数组(三)
Java语言基础组成:关键字.标识符.注释.常量和变量.运算符.语句.函数.数组 一.标识符 标识符是在程序中自定义的一些名称,由大小写字母[a-zA-Z],数字[0-9],下划线[ _ ],特殊字符 ...
- logstash5.5 数据采入elasticsearch5.5(基于x-pack)
logstash5.5 数据采入elasticsearch5.5(基于x-pack) 以采集redis日志信息为例 redis日志文件.MQ(redis).logstash主机:10.10.83.16 ...
- CPU密集型和I/O密集型区别
CPU密集型 一些进程绝大多数时间在计算上,称为计算密集型(CPU密集型)computer-bound.一些大量循环的代码(例如:图片处理.视频编码.人工智能等)就是CPU密集型. I/O密集型 有一 ...
- java实现Md5加密工具类
场景:平常我们用户注册的密码保存到数据库都不会是明文存储的.都是经过加密之后的.因为保证用户的安全性.我们通常是用md5算法来加密的. 这个只能算是一个工具类.没必要了解里面是怎么实现的.拿来用就可以 ...
- 微信接口开发之高级篇系列【微信权限封装类WechatAuth】
ThinkPHP框架目录结构: <?php /** * Created by PhpStorm. * User: Tinywan * Date: 2016/9/11 * Time: 9:55 * ...
- 关于javaBean,pojo,EJB
JavaBean是公共Java类 1.所有属性为private.2.提供默认无参构造方法.3.类属性通过getter和setter操作.4.实现serializable接口.
- Spring session(redis存储方式)监听导致创建大量redisMessageListenerContailner-X线程
待解决的问题 Spring session(redis存储方式)监听导致创建大量redisMessageListenerContailner-X线程 解决办法 为spring session添加spr ...