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 某省调查城镇交通状况,得到现有城镇道路统计表,表中列出了每条道路直接连通的城镇.省政府“畅通工程”的目标是使全省任何两个城镇间都可以实现交通(但不一定有直接的道路相连,只要互相 ...
随机推荐
- 面向对象——类的内置attr(三十三)
class Foo: x=1 def __init__(self,y): self.y=y def __getattr__(self, item): print('----> from geta ...
- 洛谷【P1523】旅行商的背包(算法导论 15-1) 题解
P1523 旅行商简化版 题目背景 欧几里德旅行商\((Euclidean Traveling Salesman)\)问题也就是货郎担问题一直是困扰全世界数学家.计算机学家的著名问题.现有的算法都没有 ...
- python influxdb
Git:https://github.com/influxdata/influxdb-python 帮助文档:http://influxdb-python.readthedocs.io/en/late ...
- Java主要版本平台
- Hadoop基础-HDFS的读取与写入过程剖析
Hadoop基础-HDFS的读取与写入过程剖析 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 本篇博客会简要介绍hadoop的写入过程,并不会设计到源码,我会用图和文字来描述hdf ...
- 函数和常用模块【day06】:random模块(三)
本节内容 1.简述 2.random模块 3.string模块 4.生成随机数 一.简述 我们经常会使用一些随机数,或者需要写一些随机数的代码,今天我们就来整理随机数模块:random模块 二.ran ...
- Linux 命令详解(三)./configure、make、make install 命令
这些都是典型的使用GNU的AUTOCONF和AUTOMAKE产生的程序的安装步骤 一.基本信息 1../configure 是用来检测你的安装平台的目标特征的.比如它会检测你是不是有CC或GCC,并不 ...
- GC.SuppressFinalize()的正确用法
SuppressFinalize函数是: 该方法在对象头中设置一个位,系统在调用终结器时将检查这个位.obj 参数应为此方法的调用方. 实现 IDisposable 接口的对象可以从 IDisposa ...
- ssh 登录出现Are you sure you want to continue connecting (yes/no)?解决方法
ssh 登录出现Are you sure you want to continue connecting (yes/no)?解决方法 1,可以使用ssh -o 的参数进行设置例如: ssh -o St ...
- Java 连接 SqlServer工具类
1.下载 server2008R2驱动jar包 下载jar包 http://www.microsoft.com/zh-cn/download/confirmation.aspx?id=21599 2. ...