0% found this document useful (0 votes)
8 views63 pages

Week 9 - Greedy Algorithm 3

nothing

Uploaded by

abidformuli100
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
8 views63 pages

Week 9 - Greedy Algorithm 3

nothing

Uploaded by

abidformuli100
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
You are on page 1/ 63

Greedy Algorithms

The Shortest-Path Problem


 The shortest-path problem is:
 For a given starting point and destination, what

is the cheapest route?


 The most commonly encountered problem

associated with weighted graphs is that of finding


the shortest path between two given vertices.
 The solution to this problem is applicable to a

wide variety of real-world situations.


Dijkstra’s Algorithm
 The solution for the shortest-path problem is called
Dijkstar’s algorithm after Edsger Dijkstra, who
first described it in 1959.
 This algorithm is based on the adjacency matrix
representation of a graph.
 This algorithm finds not only the shortest path
from one specified vertex to another, but also the
shortest paths from the specified vertex to all the
other vertices.
Java code
 The key data structure in the shortest-path
algorithm is an array that keeps track of the
minimum distances from the starting vertex to the
other vertices.
 During the execution of the algorithm, these
distances are changed, until at the end they hold
the actual shortest distances from the start.
 In the example code, this array is called spath[].
 It is only necessary to store the parent of the
destination vertex.
 The parent is the vertex reached just before the
destination.
 There are several ways to keep track of the parent
vertex, but we choose to combine the parent with
the distance and put the resulting object into the
spath[] array.
 We call this class of objects Distpar (for distance
parent).
class distpar {
public int distance;
public int parentvert;
public distpar (int pv, int d) {
distance = d;
parentvert = pv;
}
}
 The path() method:
 The path() method carries out the actual

shortest-path algorithm.
 It uses the distpar class and the vertex class,

which we saw in the mstw.


 The path() method is a member of the graph

class.
public void path() {
int starttree =0;
vertexlist[starttree].isintree = true;
ntree = 1;
for(int j=0; j<nverts; j++)
{
int tempdist = adjmat[starttree][j];
spath[j] = new distpar(starttree, tempdist);
}
while(ntree < nverts) {
int indexmin = getmin();
int mindist = spath[indexmin].distance;
if(mindist == infinity) {
System.out.println("There are unreachable vertices");
break;
}
Else {
currentvert = indexmin;
starttocurrent = spath[indexmin].distance;
}
vertexlist[currentvert].isintree =true;
ntree++;
adjust_spath();
}
displaypaths();
ntree =0;
for(int j=0; j<nverts; j++)
vertexlist[j].isintree = false;
}
 The starting vertex is always at index 0 of the
vertexlist[ ] array.
 Step 1:
 The first task in path() is to put this vertex into

the tree.
 As the algorithm proceeds, we will be moving

other vertices into the tree as well.


 The vertex object contain a flag that indicates

whether a vertex object is in the tree.


 Putting a vertex in the tree consists of setting this
flag and incrementing ntree, which counts how
many vertices are in the tree.
 Step 2:
 Second, path() copies the distance from the

appropriate row of the adjacency matrix to


spath[ ].
 This is always row 0, because for simplicity we

assume 0 is the index of the starting vertex.


 Initially, the parent field of all the spath[ ] entries
is A, the starting vertex.
 The while loop of the algorithm terminates after

all the vertices have been placed in the tree.


 There are basically 3 actions in this loop:
 Choose the spath[ ] entry with the minimum

distance.
 Put the corresponding vertex in the tree. This

becomes the “current vertex” currentvert.


 Update all the spath [ ] entries to reflect

distances from currentvert.



 If path() finds that the minimum distance is
infinity, it knows that some vertices are
unreachable from the starting point.
 Because not all the vertices are in the tree and yet
there is no way to get to these extra vertices.
 To find the spath[ ] entry with the minimum
distance, path() calls the getmin() method.
 It steps across the spath[ ] entries and return with
the column number of the entry with the minimum
distance.
 Updating spath[ ] with adjust_spath():
 The adjust_spath() method is used to update the

spath[ ] entries to reflect new information


obtained from the vertex just inserted in the tree.
 When this routine is called, currentvert has just

been placed in the tree, and starttocurrent is the


current entry in spath [ ] for this vertex.
 The adjust_spath() method now examine each

vertex entry in spath[ ], using the loop counter


column to point to each vertex in turn.
 For each spath[ ] entry, provided the vertex is not in
the tree, it does three things:
 It adds the distance to the current (already

calculated and now in starttocurrent ) to the edge


distance from currentvert to the column vertex.
we call the result starttofringe.
 It compares starttofringe with the current entry

in spath [ ].
 If starttofringe is less, it replaces the entry in

spath [ ].
 This is the heart of Dijkstra’s algorithm.
 It keeps spath [ ] updated with the shortest
distances to all the vertices that are currently
known.
class distpar {
public int distance;
public int parentvert;
public distpar(int pv, int d) {
distance = d;
parentvert = pv;
}
}
class vertex2 {
public char label;
public boolean isintree;
public vertex2(char lab) {
label = lab;
isintree = false;
}
}
class graph2 {
private final int max_verts = 20;
private final int infinity = 10000;
private vertex2 vertexlist[];
private int adjmat[][];
private int nverts;
private int ntree;
private distpar spath[];
private int currentvert;
private int starttocurrent;
public graph2() {
vertexlist = new vertex2[max_verts];
adjmat = new int[max_verts][max_verts];
nverts = 0;
ntree = 0;
for(int j=0; j<max_verts; j++)
for(int k=0; k<max_verts; k++)
adjmat[j][k] = infinity;
spath = new distpar[max_verts];
}
public void addvertex(char lab) {
vertexlist[nverts++] = new vertex2(lab);
}
public void addedge(int start, int end, int weight) {
adjmat[start][end] = weight;
}
public void path() {
int starttree =0;
vertexlist[starttree].isintree = true;
ntree = 1;
for(int j=0; j<nverts; j++) {
int tempdist = adjmat[starttree][j];
spath[j] = new distpar(starttree, tempdist);
}
while(ntree < nverts) {
int indexmin = getmin();
int mindist = spath[indexmin].distance;
if(mindist == infinity) {
System.out.println("There are unreachable vertices");
break;
}
Else {
currentvert = indexmin;
starttocurrent = spath[indexmin].distance;
}
vertexlist[currentvert].isintree =true;
ntree++;
adjust_spath();
}
displaypaths();
ntree =0;
for(int j=0; j<nverts; j++)
vertexlist[j].isintree = false;
}
public int getmin() {
int mindist = infinity;
int indexmin = 0;
for(int j=1; j<nverts; j++) {
if(!vertexlist[j].isintree && spath[j].distance < mindist) {
mindist = spath[j].distance;
indexmin = j;
}}
return indexmin;
}
public void adjust_spath() {
int column = 1;
while(column < nverts) {
if(vertexlist[column].isintree) {
column++;
continue;
}
int currenttofringe = adjmat[currentvert][column];
int starttofringe = starttocurrent + currenttofringe;
int spathdist = spath[column].distance;
if(starttofringe < spathdist) {
spath[column].parentvert = currentvert;
spath[column].distance = starttofringe;
}
column++;
}
}
public void displaypaths() {
for(int j=0; j<nverts; j++) {
System.out.print(vertexlist[j].label + "=");
if(spath[j].distance == infinity)
System.out.print("inf");
else
System.out.print(spath[j].distance);
char parent = vertexlist[spath[j].parentvert].label;
System.out.print("(" + parent + " ) ");
}
System.out.println(" ");
}
}
class pathapp {
public static void main (String[] args) {
graph2 thegraph = new graph2();
thegraph.addvertex('A');
thegraph.addvertex('C');
thegraph.addvertex('B');
thegraph.addvertex('D');
thegraph.addvertex('E');
thegraph.addedge(0,1,50);
thegraph.addedge(0,3,80);
thegraph.addedge(1,2,60);
thegraph.addedge(1,3,90);
thegraph.addedge(2,4,40);
thegraph.addedge(3,2,20);
thegraph.addedge(3,4,70);
thegraph.addedge(4,1,50);
System.out.println("Shotest paths");
thegraph.path();
System.out.println(); } }
Bi-connected Graph
 A graph with no articulation points is called bi-
connected or non-separable.
 A vertex whose removal, along with its incident
edges, disconnects the remaining vertices is called
an articulated point or a cut-vertex.
 If one node and its edges are removed from the
graph, all of the other nodes in the bi-connected
component can still reach any other.
 The graph in the next figure shows a connected
graph that has three bi-connected components.
 The first bi-connected component has the nodes

labeled A, B, C, and D.
 The 2nd has the nodes labeled D, E, F, G, and H.

 The 3rd has the nodes H and I.


 Determining the bi-connected components of a
network indicates how stable the network can be
under degraded conditions.
 So, if all computers on a network are part of the
bi-connected component of the related graph, we
know that the network will continue to function
even if one of the computers is down.
 We could identify the articulation points in a
brute force manner as following:
 Remove one node at a time and using one of our

traversal methods to see if the remaining nodes


are still connected.
 If they are, the node we removed is not an

articulation point, but if they are not, it is an


articulation point.
 This means that we would have to do N traversals
of a graph with N nodes.
 This process would be O(N2).
 By keeping a little additional information while
we are traversing, we can identify the articulation
points and the bi-connected components on one
traversal.
 Think about paths in the graph in next figure

that begin at node F.


 You should see that no matter what order the

nodes are visited in, the paths from node F to


nodes A, B, and C must go through node D.
 This means that node D is an articulation point
and the sub-graph containing nodes A, B, C, and
D is a bi-connected component.
 We base our algorithm on depth-first search.

 A depth-first search will follow edges into a

graph until a dead end is reached where there


are no unvisited nodes adjacent to the current
node.
 When we reach a dead end, we will back up, but
now our algorithm will return information about
how high up in the depth-first search tree we
could have gone at the dead end.
 These back edges in the search tree indicate a

cycle back in the graph.


 All the nodes in a cycle must be part of the same

bi-connected component.
 To accomplish this algorithm, we will keep a
count of how many nodes of the graph we have
visited.
 Each node will be assigned an index number
indicating when is it visited.
 In other words, the first node visited will be
numbered 1, the second will be numbered 2, and
so on. When we reach a dead end, we will look at
all of the adjacent nodes (except for the node we
just came from) and will use the smallest index
number as our back index.
 If there is just one adjacent node (the one we just
came from), we will return the dead end node’s
index as our back index.
 When we return to a node that is not the root of
the search tree, we will compare the back index
value that was returned.
 If that value is greater than or equal to the current
node’s index value, the sub-tree just visited
(minus any previously found bi-connected
components) is a bi-connected component.
 Each internal node of the depth-first search tree
will return the smallest value from among the
indices of adjacent nodes and any back indices
returned to it.
 How would this process work in graph of the
figure? If we begin at node F, it would be assigned
an index of 1.
 We move to node D (index 2), then nodes B (index
3), A (index 4), and C (index 5).
 Node C is a dead end, and we have back edges to
nodes A, B, and D. The index on node D is
smallest, so a value of 2 would be returned to
node A as the back index. At node A, because the
value of 2 is less than node A’s index, it is not an
articulation point.
 The value of 2 is the smallest so far, and it is also
returned to node B.
 This continues until we get back to node D, where
we find that the back index returned is the same as
node D’s index, and so the nodes A, B, C, and D
make up a bi-connected component.
 We return to the root of the search tree at node F
and then move off to node E (index 6), followed by
node G (index 7), and node H (index 8). We next
traverse down to node I (index 9), and because it
is a dead end with no adjacent nodes other than H,
we return its index as the back index.
 When node H receives a value of 9 from node I,
which is greater than the index of node H, we find
another biconnected component with nodes H and
I.
 Node H now considers the values of 1 (the back
edge to F), 9 (returned from node I), and 8 (node
H’s index), returning the smallest of these to node
G and then to node E.
 This value is then returned by node E to the root
node, and because all nodes have been visited,
those that remain (nodes D, E, F, G, and H)
comprise the final biconnected component.
 In Fig. 6.10 we see the result of this process, and
from this we can see that the articulation points in
the original graph are nodes D and H, which are
the only nodes that appear in two separate
components.
Java Implementation
import java.io.*;
import java.util.*;
import java.util.LinkedList;
class testBut{
private int V;
private LinkedList<Integer> adj[];
int time = 0;
static final int NIL = -1;
testBut(int v){
V = v;
adj = new LinkedList[v];
for (int i=0; i<v; ++i)
adj[i] = new LinkedList();
}
void addEdge(int v, int w){
adj[v].add(w);
adj[w].add(v);
}
boolean isBCUtil(int u, boolean visited[], int disc[],int low[],int parent[])
{
int children = 0;
visited[u] = true;
disc[u] = low[u] = ++time;
Iterator<Integer> i = adj[u].iterator();
while (i.hasNext()){
int v = i.next();
if (!visited[v]){
children++;
parent[v] = u;
if (isBCUtil(v, visited, disc, low, parent))
return true;
low[u]= Math.min(low[u], low[v]);
if (parent[u] == NIL && children > 1)
return true;
if (parent[u] != NIL && low[v] >= disc[u])
return true;
}
else if (v != parent[u])
low[u] = Math.min(low[u], disc[v]);
}
return false;
}
boolean isBC(){
boolean visited[] = new boolean[V];
int disc[] = new int[V];
int low[] = new int[V];
int parent[] = new int[V];
for (int i = 0; i < V; i++){
parent[i] = NIL;
visited[i] = false;
}
if (isBCUtil(0, visited, disc, low, parent) == true)
return false;
for (int i = 0; i < V; i++)
if (visited[i] == false)
return false;
return true;
}
public static void main(String args[]){
testBut g2 =new testBut(5);
g2.addEdge(0, 1);
g2.addEdge(0, 2);
g2.addEdge(2, 1);
g2.addEdge(0, 3);
g2.addEdge(3, 4);
g2.addEdge(2, 4);
if (g2.isBC())
System.out.println("Yes");
else
System.out.println("No");
}
}
End of Chapter 9

Any Question?

You might also like