(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. Windows 服务程序、窗口界面、桌面交互、与远程桌面

    昨天用c写了一个windows服务(服务内部带一个gui窗口+系统托盘),在windows xp sp3上测试,启动服务后,系统托盘显示正常. 但在另一台windows 2003 sp2 上测试(通过 ...

  2. MUI 当input聚焦之后,弹出自带的键盘之后,内容往上移动

    1)有时候为了用户更好的体验,当input聚焦之后,手机自带的键盘弹出的时候,页面的内容也要跟着滚动,好让键盘不遮住input 只要把input标签放到mui-content这个类里面就可以了 < ...

  3. Java 读取文件的内容

    Java 读取文件的内容 1) CLASS_NAME: 换成自己真实的类名 2) /page/test.json: 换成自己真实的page 3) FileUtils: 来自于org.apache.co ...

  4. 基于 Dojo toolkit 实现 web2.0 的 MVC 模式

    前言 MVC 模式是设计模式中的经典模式,它可以有效的分离数据层,展示层,和业务逻辑层.Web2.0 技术由于其良好的用户体验被广泛应用于 WEB 应用的展示层.但是在传统的 web 开发中,展示层的 ...

  5. HashMap按照value排序的实现

    一.实现的思想 将HashMap中的元素按照Entry<Key,Value>类型存入到LinkedList集合中. 实现自定义排序,对LinkedList集合排序. LinkedList集 ...

  6. impala记录-安装kudu和impala

    1.配置/etc/yum.repos.d clouder-kudu.repo [cloudera-kudu]# Packages for Cloudera's Distribution for kud ...

  7. servlet 获取 post body 体用流读取为空的问题【转】

    引用自: http://www.zicheng.net/article/982028.htm 目前基于rest风格的很多API开始使用通过body data来传输来代替之前的key-value传输方式 ...

  8. HDU - 4901 The Romantic Hero(dp)

    https://vjudge.net/problem/HDU-4901 题意 给n个数,构造两个集合,使第一个集合的异或和等于第二个集合的相与和,且要求第一个集合的元素下标都小于第二个集合的元素下标. ...

  9. luogu 4401 矿工配餐 多维dp

    五维dp,记忆化搜索会MLE超内存,所以用滚动数组,十分经典 五维dp #include <bits/stdc++.h> using namespace std; ; ][][][],la ...

  10. centos7 redmine安装过程

     mysql安装配置   redmine 部署过程 redmin官方文档写的太烂加上不熟悉ruby搞了半天,回到家后觉得还是记录下好,希望可以帮助有需要的人,少走弯路. 版本说明 下面的版本很重要re ...