(a)首先对有向无环图进行拓扑排序,再按拓扑排序的逆序依次计算每个顶点的cost值,每个顶点的cost值为自身的price值与相邻顶点间的cost值得最小值

(b)求出图中的每一个强连通分量,并把所有得强连通分量看成是一个有向无环图,设每一个强连通分量的price值为该强连通分量中顶点的最小的price值。然后再按(a)中的步骤处理DAG

 package org.xiu68.ch03.ex11;

 import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.List;
import java.util.Stack; public class Ex3_25 {
public static void main(String[] args) {
// TODO Auto-generated method stub
int[][] edges=new int[][]{
{0,0,1,0,0,0},
{0,0,0,1,0,0},
{0,0,0,0,1,1},
{0,0,0,0,1,1},
{0,0,0,0,0,0},
{0,0,0,0,0,0}
};
int[] price=new int[]{2,3,6,1,4,5};
MGraph2 m1=new MGraph2(edges, price);
m1.getCost();
System.out.println("*****************");
m1.getSccCost();
//输出
/*
cost[0]:2
cost[1]:1
cost[2]:4
cost[3]:1
cost[4]:4
cost[5]:5
*****************
cost[0]=2
cost[1]=1
cost[2]=4
cost[3]=1
cost[4]=4
cost[5]=5
*/
System.out.println("*******************");
int[][] edges1=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}
};
int[] price1=new int[]{6,7,9,5,3,4,2};
MGraph2 m2=new MGraph2(edges1, price1);
m2.getSccCost();
//输出
/*
cost[0]=6
cost[1]=2
cost[2]=2
cost[3]=2
cost[4]=2
cost[5]=2
cost[6]=2
*/
} } class MGraph2{
private int[][] edges; //有向图
private int[][] rEdges; //有向图的反向图
private int vexNum; //顶点数量
private int[] price; //每个顶点的相对价格
private int[][] sccEdges; //强连通分量(DAG)之间的关系
private Stack<Integer> stack; //存储反向图深度优先遍历的post值 public MGraph2(int[][] edges,int[] price){
this.edges=edges;
this.vexNum=edges.length;
this.price=price;
this.stack=new Stack<>();
this.rEdges=new int[vexNum][vexNum];
this.sccEdges=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];
}
}
} //**********************************************************
//针对有向无环图,获取每个顶点的cost值
public void getCost(){
ArrayDeque<Integer> queue=new ArrayDeque<Integer>(); //存取拓扑排序的逆序
int[] cost=new int[vexNum];
for(int i=0;i<vexNum;i++)
cost[i]=price[i];
topoSort(queue,edges,vexNum); //依次处理每个顶点,每个顶点取自身的price值和邻接点的cost值得最小值
while(!queue.isEmpty()){
int v=queue.poll();
for(int i=0;i<vexNum;i++){
if(edges[v][i]==1 && cost[i]<cost[v])
cost[v]=cost[i];
}
}
for(int i=0;i<vexNum;i++)
System.out.println("cost["+i+"]:"+cost[i]);
}
//求拓扑排序的逆序
public void topoSort(ArrayDeque<Integer> queue,int[][] edgeArray,int vertexNum){
boolean[] visited=new boolean[vertexNum];
for(int i=0;i<vertexNum;i++){
if(!visited[i])
topoDFS(queue,visited,edgeArray,vertexNum,i);
}
}
//深度优先遍历求拓扑排序
public void topoDFS(ArrayDeque<Integer> queue,boolean[] visited,int[][] edgeArray,int vertexNum,int v){
visited[v]=true;
for(int i=0;i<vertexNum;i++){
if(edgeArray[v][i]==1 && !visited[i]){
topoDFS(queue,visited,edgeArray,vertexNum,i);
}
}
queue.add(v);
} //****************************************************************
//针对所有有向图的情况,获取每个顶点的cost值
public void getSccCost(){
rDFSTraverse(); //先对反向图进行深度优先遍历 List<List<Integer>> sccs=new ArrayList<>(); //存放每一个强连通部件对应的顶点 boolean[] visited=new boolean[vexNum]; //记录深度优先遍历原图过程中非当前强连通分量已经访问的顶点
int[] visitedN=new int[vexNum]; //记录顶点属于第几个强连通分量
int n=0; //第几个强连通部件 for(int i=0;i<vexNum;i++){
visitedN[i]=-1;
} //依次出栈,并从该顶点开始对原图进行深度优先遍历,获取每个强连通分量对应的顶点
//并获取DAG之间的关系
while(!stack.isEmpty()){
int v=stack.pop();
if(!visited[v]){
sccs.add(new ArrayList<Integer>());
List<Integer> vexs=new ArrayList<>(); //获取第n个强连通分量的顶点 sccDFS(visited,visitedN,v,sccs,vexs,/*isSinkSCC,*/n);
//为了知道遍历第n个强连通分量之前已经访问过哪些顶点
//遍历完一个强连通分量再设visited值
for(int i=0;i<vexs.size();i++){
visited[vexs.get(i)]=true;
}
n++;
}
} int[] sccPrice=new int[sccs.size()];
int[] sccCost=new int[sccs.size()];
//将每个强连通分量的price值设为强连通分量中price值最小的顶点的price值
for(int i=0;i<sccs.size();i++){
sccPrice[i]=Integer.MAX_VALUE;
for(int j=0;j<sccs.get(i).size();j++){
//sccs.get(i).get(j) 第i个强连通分量的第j个顶点
if(price[sccs.get(i).get(j)]<sccPrice[i]){
sccPrice[i]=price[sccs.get(i).get(j)];
}
}
} //对DAG进行拓扑排序
ArrayDeque<Integer> topoQueue=new ArrayDeque<>();
topoSort(topoQueue, sccEdges, sccs.size()); for(int i=0;i<sccs.size();i++)
sccCost[i]=sccPrice[i]; //topoSort(topoQueue,edges,vexNum);
////依次处理DAG中每个顶点,每个顶点取自身的price值和邻接点的cost值得最小值
while(!topoQueue.isEmpty()){
int v=topoQueue.poll();
for(int i=0;i<sccs.size();i++){
if(sccEdges[v][i]==1 && sccCost[i]<sccCost[v])
sccCost[v]=sccCost[i];
}
} //visitedN[i] 第i个顶点在第几个强连通分量中
for(int i=0;i<vexNum;i++)
System.out.println("cost["+i+"]="+sccCost[visitedN[i]]);
} //对原图进行深度优先遍历
//在汇点强连通部件中对某个顶点进行深度优先遍历则刚好访问该强连通部件的所有顶点
private void sccDFS(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]){
//i为其他强连通分量的顶点,所以当前强连通分量有一条边指向i所在的强连通分量
sccEdges[n][visitedN[i]]=1;
}else if(visitedN[i]!=n){
sccDFS(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);
}
}

Ex 3_25 图中每个顶点有一个相关价格..._十一次作业的更多相关文章

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

    (a) 可以用图中的每一个顶点表示街道中的每个十字路口,由于街道都是单行的,所以图是有向图,若从一个十字路口都有一条合法的路线到另一个十字路口,则图是一个强连通图.即要验证的是图是否是一个强连通图. ...

  2. Swift 中使用 SwiftyJSON 制作一个比特币价格 APP

    Swift 中处理 JSON 数据有很多种方式,可以使用原生的 NSJSONSerialization,也可以使用很多第三方库.原生的 NSJSONSerialization 方式这篇文章中介绍过.这 ...

  3. Ex 2_23 如果一个数组超过半数的元素都相同时,该数组被称为含有一个主元素..._第二次作业

    将数组A划分为两个数组A1和A2 ,各含有A的一半元素或一半多一个.若A中含有主元素x,则A1和A2中至少有一个数组含有主元素x,对A1和A2递归地计算有无主元素,若A只含有一个元素,则A的主元素就是 ...

  4. Ex 2_16 给定一个无穷数组..._第二次作业

    先比较数组的A[0]元素,若不相等接下来比较A[1],A[2],A[4],A[8]…,若找到一个区间A[2n-1]<x<A[2n],再对这个区间进行折半查找操作.总的时间为O(logn). ...

  5. _DataStructure_C_Impl:求图G中从顶点u到顶点v的一条简单路径

    #pragma once #include<stdio.h> #include<stdlib.h> #define StackSize 100 typedef int Data ...

  6. javascript实现有向无环图中任意两点最短路径的dijistra算法

    有向无环图 一个无环的有向图称做有向无环图(directed acycline praph).简称DAG 图.DAG 图是一类较有向树更一般的特殊有向图, dijistra算法 摘自 http://w ...

  7. 【 D3.js 进阶系列 — 2.1 】 力学图的事件 + 顶点的固定

    本章讨论在力学图中经常使用到的事件( Event ),然后对[p=555">进阶 - 第 2.0 章]的人物关系图进行改进.使用户可以固定拖拽的对象. 在[入门 - 第 9.2 章]和 ...

  8. Dijkstra 算法,用于对有权图进行搜索,找出图中两点的最短距离

    Dijkstra 算法,用于对有权图进行搜索,找出图中两点的最短距离,既不是DFS搜索,也不是BFS搜索. 把Dijkstra 算法应用于无权图,或者所有边的权都相等的图,Dijkstra 算法等同于 ...

  9. 《逐梦旅程 WINDOWS游戏编程之从零开始》笔记5——Direct3D中的顶点缓存和索引缓存

    第12章 Direct3D绘制基础 1. 顶点缓存 计算机所描绘的3D图形是通过多边形网格来构成的,网网格勾勒出轮廓,然后在网格轮廓的表面上贴上相应的图片,这样就构成了一个3D模型.三角形网格是构建物 ...

随机推荐

  1. MSSQL 转 ACCESS 在表格结构上应注意的

    今天在把一个MSSQL数据库转为ACCESS发现了一些问题: 在MSSQL表格中的一个(标识)递增字段转到ACCESS后,变成了 “数字”类型,而不是“自动编号”. 而当在Access中,一个字段类型 ...

  2. Word2010中的页眉怎样删除和添加横线

    http://jingyan.baidu.com/article/f79b7cb3bb3c629144023e05.html 我们在使用Word2010编辑文档中时,有时需要在页眉下方删除或添加一条横 ...

  3. pyautogui_pdf内容提取到excel内_3

    sklearn实战-乳腺癌细胞数据挖掘(博主亲自录制视频) https://study.163.com/course/introduction.htm?courseId=1005269003& ...

  4. GO语言的进阶之路-goroutine(并发)

    GO语言的进阶之路-goroutine(并发) 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 有人把Go比作21世纪的C 语言,第一是因为 Go语言设计简单,第二,21世纪最重要的 ...

  5. WebLogic 中的基本概念【转】

    完全引用自: WebLogic 中的基本概念 WebLogic 中的基本概念 上周参加了单位组织的WebLogic培训,为了便于自己记忆,培训后,整理梳理了一些WebLogic的资料,会陆续的发出来, ...

  6. golang数组声明

    格式 初始化数组 {}中的元素数不能大于[]中的数字,并且长度在初始化后不能改变,定义数组时需指定长度 ... var arrName [num]type = [num]type{value, val ...

  7. 通过read()读文件

    一.在POSIX中的定义 #include <unistd.h> ssize_t read(int fd, void *buf, size_t len); 二.调用read()的可能结果 ...

  8. 2018秋寒假作业4- -PTA编程总结1

    PTA1打印沙漏.打印沙漏中的“沙漏形状”,就是每行输出的奇数符号与各行符号中心对齐:相邻两行符号数相差2:符号数从大到小递减到1,再从小到大递增.在做的时候出了几次错,编译发先是几个小地方出错了.以 ...

  9. linux 链接理解

    1.软链接 只包含另外软链接的基本信息, 生成与源文件不同的节点号, 可以链接目录.不同网络的文件 2.硬链接只能链接文件,不会生成节点号,说白了就是指针,指向同个文件,所以链接的节点号与源节点号一致

  10. 【金色】种瓜得瓜,种豆得豆 Gym - 102072H (线段树)

    题目链接:https://cn.vjudge.net/problem/Gym-102072H 题目大意:中文题目 具体思路:通过两棵线段树来维护,第一棵线段树来维护当前坐标的点的日增长速度(默认每一年 ...