(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 判断图是否是一个强连通分量 判断点是否在汇点强连通分量中_十一次作业的更多相关文章

  1. Ex 3_25 图中每个顶点有一个相关价格..._十一次作业

    (a)首先对有向无环图进行拓扑排序,再按拓扑排序的逆序依次计算每个顶点的cost值,每个顶点的cost值为自身的price值与相邻顶点间的cost值得最小值 (b)求出图中的每一个强连通分量,并把所有 ...

  2. ViewPager 滑动一半的判断方法以及左滑右滑判断

    做项目的时候,会碰到用viewpager + fragments去实现多页滑动.有些时候需要完成:界面在滑动到一半或是一半以上的时候,需要把title之类的切换到下一个页面.这个时候仅仅依赖Viewp ...

  3. POJ 1860 Currency Exchange(如何Bellman-Ford算法判断图中是否存在正环)

    题目链接: https://cn.vjudge.net/problem/POJ-1860 Several currency exchange points are working in our cit ...

  4. 判断图连通的三种方法——dfs,bfs,并查集

    Description 如果无向图G每对顶点v和w都有从v到w的路径,那么称无向图G是连通的.现在给定一张无向图,判断它是否是连通的. Input 第一行有2个整数n和m(0 < n,m < ...

  5. POJ_1064_Cable_master_(二分,假定一个解并判断是否可行)

    描述 http://poj.org/problem?id=1064 有n条绳子,长度分别为l[i].如果从它们中切割出k条长度相同的绳子的话,这k条绳子每条最长能有多少? Cable master T ...

  6. 金牌分析师助力 鲁泰A图谋再造一个“鲁泰”?_财经_中国网

    金牌分析师助力 鲁泰A图谋再造一个"鲁泰"?_财经_中国网 金牌分析师助力 鲁泰A图谋再造一个"鲁泰"?

  7. 《剑指Offer》第1题(Java实现):在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。

    一.题目描述 在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序.请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该 ...

  8. Github作为图床的一个小坑

    Github作为图床的一个小坑 前言 听了少铭同学建议把github作为图床,结果遇到了一个小坑,总是显示不出来图片. 问题描述与解决 形如下的链接是显示不出来的: https://github.co ...

  9. HDU-1232 畅通工程 (并查集、判断图中树的棵数)

    Description 某省调查城镇交通状况,得到现有城镇道路统计表,表中列出了每条道路直接连通的城镇.省政府“畅通工程”的目标是使全省任何两个城镇间都可以实现交通(但不一定有直接的道路相连,只要互相 ...

随机推荐

  1. A1033. To Fill or Not to Fill

    With highways available, driving a car from Hangzhou to any other city is easy. But since the tank c ...

  2. json模块和pickle模块(二十二)

    之前我们学习过用eval内置方法可以将一个字符串转成python对象,不过,eval方法是有局限性的,对于普通的数据类型, json.loads和eval都能用,但遇到特殊类型的时候,eval就不管用 ...

  3. 中文参考文献如何导入到endnote中

    比如我想在文献中插入“2型糖尿病患者并发脑卒中的前瞻性研究”这篇参考文献,在主题里面输入文献标题,勾选我们要找的文献,点击“导出/参考文献” 导出来以后,点击屏幕右下角界面的“导出/参考文献”,下图红 ...

  4. JavaSE学习总结(十九)—— Java Web 综合应用(JSP、Servlet、IDEA、MySQL、JUnit、AJAX、JSON)

    一.使用Servlet+JDBC+MySQL+IDEA实现商品管理 1.1.创建项目 打开IntelliJ IDEA开发工具.点击Create New Project创建一个新的Web项目 选择Jav ...

  5. (next_permutation) 排列2 hdu 1716

    排列2 Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submis ...

  6. JavaSE学习总结(九)—— Java访问数据库(JDBC)

    一.JDBC简介 JDBC(Java Data Base Connectivity,java数据库连接)是一种用于执行SQL语句的Java API,可以为多种关系数据库提供统一访问,它由一组用Java ...

  7. 虚拟机下安装ubuntu后root密码登录失败的问题

    问题描述: 在虚拟机下安装了ubuntu中要输入用户名,一般情况下大家都会输入一个自己的网名或绰号之类的,密码也在这时设置过了. 但是当安装成功之后,使用命令#su root,然后输入刚才设置的密码, ...

  8. Jmeter调用 Json接口测试之关键点申明Content-Type类型

    背景: 最近,在做接口测试发现创建运单接口,通过普通表单请求总是失败,开始我以为是后端接口出现问题,但通过前端页面都能创建运单,F12打开浏览器开发者模式,获取该接口请求入参发现,请求的数据格式是js ...

  9. android ListView 分页加载数据

    1.mainActivity <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" ...

  10. sql server存储过程简单的使用

    --创建存储过程 create proc test_proc @date datetime as select * from t_user where times between ),),),),' ...