(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. 【CH5105】cookies 贪心+DP

    通过邻项交换法可知,怨气值大的孩子分得的饼干数也应该多(否则交换之后得到的解更优). 观察目标函数的性质,可知目标函数本身是由孩子饼干数的相对大小得到,因此此题中关注的是相对大小. 状态设计:\(dp ...

  2. php in_array 的一个坑

    in_array('', [0]); // true 因为 php 里面 '' == 0 的结果是 true,这种情况即使 in_array 第三个参数传了 true,还是不能达到想要的效果,只能特殊 ...

  3. Win7任务栏合并

    在“任务栏” -> "任务栏按钮" -> "始终合并.隐藏标签” 另外,如果想使时间显示详细,可消去“使用小图标”

  4. MySQL服务安装

    1.将mysql的安装文件放入服务器里面 2.进行yum源的修改 3.依次安装mysql的5个文件 最后一个server需要的依赖太多,所以用yum进行安装. 或者直接全部用yum进行安装 6.进行m ...

  5. Maven 自动打包上传到私服 Nexus

    转载于:http://blog.csdn.net/jerome_s/article/details/54410178           Maven获取jar的默认顺序是         

  6. python小demo-01: 线程池+多进程实现cpu密集型操作

    起因: 公司有一个小项目,大概逻辑如下: 服务器A会不断向队列中push消息,消息主要内容是视频的地址,服务器B则需要不断从队列中pop消息,然后将该视频进行剪辑最终将剪辑后的视频保存到云服务器.个人 ...

  7. TCP和UDP基本原理

    TCP和UDP基本原理 传输层的主要任务就是建立应用程序间的端到端连接,并且为数据传输提供可靠或不可靠的通信服务,TCP/IP协议族的传输层协议主要包括TCP和UDP ,TCP是面向连接的可靠的传输层 ...

  8. Linux下环境变量设置技巧

    Linux下环境变量设置技巧,不用/etc/profile而是在/etc/profile.d目录下新建特定的shell文件来设置 区别: 1.两个文件都是设置环境变量文件的,/etc/profile是 ...

  9. 学习windows编程 day4 之 绘制随机矩形和peekMessage

    #include <windows.h> #include <strsafe.h> LRESULT CALLBACK WndProc(HWND hwnd, UINT messa ...

  10. 【JUC】JDK1.8源码分析之ReentrantReadWriteLock

    重入锁ReentrantLock是排他锁,排他锁在同一时刻仅有一个线程可以进行访问,但是在大多数场景下,大部分时间都是提供读服务,而写服务占有的时间较少.然而读服务不存在数据竞争问题,如果一个线程在读 ...