Sei sulla pagina 1di 5

Yi Zhai (447759337)

HW1

C OM S 511, September 3, 2015

1: Modify depth-first search so that it assigns to each vertex v V an integer label cc(v), such that
cc(u) = cc(v) if u and v are in same connected component. The running time of your algorithm should
be O(V + E).
(a) Algorithm:
General Idea: Add a label to mark the vertex when using DFS.
Pseudo code:
DFS(G)
for each vertex u V [G]
do u.color WHITE
//Initialize all vertex to white to label their status as undiscovered
u. NIL
//Initialize all vertexs parent to NIL
time 0
//Initialize time to zero
label 0
//Initialize label to zero
for each vertex u V [G]
do if u.color = W HIT E
then label label + 1
//Set vertexs label as a marker of a connected component
DFS-SEARCH(u, label)
//Start to search
DFS-SEARCH(u, label)
u.color GRAY
//Set vertex as gray when they firstly discovered
u.cc label
//Set vertexs label
time time + 1
//Increase time 1 unit
u.d time
//Set vertexs discover time
for each v Adj[u]
//Start to search every vertex which is adjacent to u
do if v.color = W HIT E
then v. u
//If vertex is white(undiscovered), set its parent as u
DFS-SEARCH(v, label)
Recursively search every vertex
u.color BLACK
//Set u as black when every adjacent vertex is done
time time + 1
//Increase time-line
u.f time
//Set us finish time
Correctness:
When DFS-SEARCH is called to generate a new tree in the DFS forest, label is increased by 1, which
means every vertex visited by DFS-SEARCH inside the same tree will be labeled with same label value.
Thus u.cc = v.cc if and only if u and v are searched in the same DFS-SEACH call coming from DFS.
Then we need to prove that the vertices touched by the DFS-SEARCH call from DFS are the vertices in
one connected component of G.
In the pseudo-code, we consider u as the first vertex searched by DFS-SEARCH in a component. Since all
vertices were marked as WHITE initially, we can say all vertices are descendants of u by white-path
theorem, which means these vertices will be visited before DFS-SEARCH return to DFS. That gives us a
fact that if two vertices are touched in the same call in DFS-SEARCH from DFS, they are in the same
connected component since they will be touched only by paths found in adjacent lists.
And, every vertex will be labeled, since we know ultimately every vertex in the G will be searched by DFS.
1

Yi Zhai (447759337)

HW1

C OM S 511, September 3, 2015

Running time:
From the pseudo-code, a vertex will be visited only if its color is white. After we visit the vertex, it will be
marked to non-white color which means it will never be visited again. That gives us a fact that all vertices
will be visited only once. Thus, we can say O(V ) time on vertices.
Again from pseudo-code, when we start to search one vertex, say u, by its adjacent lists, we only deep into
the search if the adjacent element, say v, is not visited. This make sure we visit every edge only once.
Thus, gives us O(E).
Then in total, the running time is O(V + E).
2: A pair of wrestlers may or may not be a rivalry. Suppose we have n wrestlers and r pairs are
rivalries. Given an O(n + r) algorithm that determines whether it is possible to produce a
designation such that each rivalry is formed by two kinds of wrestlers.
(a) Algorithm:
General Idea: We generate a graph with n vertices. Each vertex present a wrestler and an edge present the
relationship between two wrestlers. We examine the graph by BFS and then check the edges to determine
the relationship.
Pseudo-code:
BFS-RIVALRY-SEARCH(G)
generate graph using adjacent lists
//Generate a graph with n vertices and r edges
for each u V {s}
u.d
//Set the distance of all vertices except s to infinity
s.d 0
//Set the the distance of start point as 0
Q
//Initialize an empty list
EN-QUEUE(Q, s)
//Put start point s into Q
While Q 6=
u DE-QUEUE(Q)
//Take the first element out of Q
for each v Adj[u]
do if v.d =
then v.d v.d + 1
//Add one unit of distance
EN-QUEUE(Q, v)
//Add adjacent vertex to the queue
for each v V
do if v.d is even
v = good guys
//If distance of a vertex is even, designate it as good guy
else
v = bad guys
// if distance of a vertex is odd, designate it as bad guy
for each (u, v) E
do if (u, v) is between an odd vertex and an even vertex.
Designation produced
else Designation not produced
Correctness:
Firstly, we make sure every vertex is visited by our algorithm. Then we designate every vertex with an even
distance as a good guy and those with odd distance as a bad guy. By checking the edges after the search the

Yi Zhai (447759337)

HW1

C OM S 511, September 3, 2015

whole graph, we can come up with the idea that the graph meet our requirement.
Running time:
The BST search will cost O(V + E) time, which is O(n + r). And the designation session will cost us
O(n) since we need to traverse every vertex. Finally the check session will cost us O(r) since we also need
to check every edge. Thus, the running time is O(n + r) overall.
3: Prove G has an Euler tour if and only if in-degree(v) = out-degree(u) for each v V . And design
an algorithm to find out the Euler tour if one exists.
(a) Proof:
Suppose for all vertices v, in-degree(v) = out-degree(v), we can traverse G from a vertex, say u, and
assemble a cycle that contains u.
We start from a source vertex, say u. By the assumption, it implies that after we take an edge((u, v) that is
a in-degree edge of v(out-degree edge of u), there must be an out-degree edge of v we have not used. Pick
that edge and continue to traverse. Each time we pick an edge of v, we take it out from our unvisited list.
By doing this continuously on all other vertices that can be reached other than u, we will finally get back to
u since, for every vertex except u, there must be a out-degree edge. The last unvisited out-degree edge of
the last visiting vertex has no other vertex to go, except u. Then G leaves us an updated graph that only u
may has unvisited out-degree edges since we start from only one of us out-degree edges.
By this point, if theres still out-degree edges of u, we continue the cycle. If we successfully visited every
edge of G, we are done. If not, since G is connected, there must be unvisited out-degree edges of a vertex,
say v, on the cycle. we start a new cycle starting from v. The cycle will only take unvisited edges and we
can finally splice this cycle into previous cycle.
That means, we firstly get a cycle, namely {u, ......, v, a, ......u} and a new cycle, namely
{v, ......, b, ......v}, then we can splice them into a cycle {u, v, ......., b, ......v, a, ......, u}. We keep doing
this continuously and splicing new cycles until we visit every edge.
(b) Algorithm:
General Idea:We need to keep track of the out-degree edges of the vertex, which means we should delete
it from our unvisited list after we search it, this makes sure all edges are visited only once. And we also
need a list to store the cycles generated by the search process, namely SEARCH-R. Meanwhile, another list
is needed to store the spliced cycles, which is the final result, namely R. Additionally, In order to merge
disjoint cycles in a constant time so that our running time wouldnt exceed O(E), we need to know where
to put the newly found cycle before we merge it into our final result R. That requires us to store the
vertices positions in R so that we dont need to go through the R to find the mutual point of the two cycles.
Pseudo-code:
EULER-SPLICE(v)
R
for any vertex u V
if u
/R
R SEARCH-CYCLE(u)
else

//Insert cycle into R if the starting point is not in R

Yi Zhai (447759337)

HW1

C OM S 511, September 3, 2015

splice SEARCH-CYCLE(u) into R just before u.


//Insert the newly found cycle into R so that it forms a big cycle
Return R
SEARCH-CYCLE(u)
SEARCH-R
//Setup an empty set to store the vertices that form a cycle.
While out-degree(u) >0
do let x be the first vertex in Adj[u]
remove x from Adj[u], decrease out-degree[u]
add x to the end of SEARCH-R
//Remove vertex and the out-degree edge from unvisited list
record position information of x
//Record the vertexs location
if out-degree(u) >0
ux
Return SEARCH-R
//Return of ordered list of vertices that form a cycle
Running Time: In SEARCH-CYCLE algorithm, since we decrease out-degree of a vertex after a iteration
and remove this vertex for further search when it has no out-degree edges, we make sure every edge is
visited only once. Thus, we make sure the running time of SEARCH-CYCLE algorithm is O(|E|).
For the SPLICE part, since we recorded the location information of the vertices in R, that ensures that we
know exactly where to merge the cycle into R. That implies it only take us constant time for merge action.
So, the algorithm running tims is O(|E|) overall.
4: Design an algorithm to find the widest paths from s to every node v in G
General Idea:We adapt Dijktsras algorithm.
Pseudo-code:
for each v V
v.width
//Initialize all vertices width to negative infinity
v. NIL
s.width =
//Initialize starting points width as infinity
QV
While Q 6=
do u EXTRACT-LARGEST-WIDTH(Q)
Take out the vertex that has the largest width
for each v Adj[u]
if v.width <max(v.width, min(u.width, weight(u, v)))
//Compare the width between v and minimum value of (width of u and the weight of (u, v))
v.width max(v.width, min(u.width, weight(u, v)))
v. = u
update Q
Reorder Q in decrease order
Correctness:
We can prove our algorithm by induction.
Statement:From the pseudo code, we can see that we are actually perform our actions on two vertices.
One is the vertex which the widest path has been found. The other one is not found.
Claim:In our algorithm, any vertices, if they are playing u role in our pseudo code, have been found the
correct widest path.
4

Yi Zhai (447759337)

HW1

C OM S 511, September 3, 2015

Base Case:If we only have a starting point, say s and its width has been set as infinity at the very
beginning, in our graph. Infinity definitely is the maximum. Thus, our claim holds.
Induction:Assume we now have a vertex, say a, is de-queued from Q since it has the largest width.
According to general idea, a.width must > other paths, which lead to a, width.
Apparently, other paths need to go through some vertices that has not been designated its largest width and
for these vertices, say b, b.width 6 a.width.
That gives us a fact that all other paths to a is constrained by b, which mean it will never greater than
a.width.
Thus, our Algorithm holds.
Running time:
If we built our Q as a binary heap, which means vertices and corresponding heap elements maintain
handles. So each EXTRACT-LARGEST-WIDTH action will take O(lgV ). We totally have V vertices, that
makes us V lgV .
For the f or loop part, we know we need to examine every edges in G and each edge is checked only once.
That means we totally have E iterations in f or loop. Inside each iteration, we need to reorder the Q again.
It takes, again, O(lgV ) to do that. So it takes O(ElgV ) time to finish the f or loop.
Thus, we combine two parts together, it will take O(V lgV + ElgV ) = O((V + E)lgV ) time overall.