Question link: http://poj.org/problem? Id = 2186
The dream of a milk cow is to become the most popular cow in the herd, that is, to be welcomed by all other cows. "Welcome" is a transmission, that is, if Niu A thinks that Niu B is popular and Niu B thinks that Niu C is popular, Niu A also implicitly thinks that Niu C is popular. Now, if you give a group of points (A, B), it means that a considers B to be popular and finds out how many of the most popular cows there are.
This is a directed graph problem. The vertices in the figure represent the cows, and the directed edge (a, B) indicates that a becomes B. The most popular ox is those that can be reached by other vertices. The most violent solution is to determine whether all other vertices can reach each vertex. The complexity of this algorithm is O (v2e), where V is the number of vertices and E is the number of directed edges. The data size of the question obviously times out.
In fact, there is an O (V + E) algorithm. This requires us to carefully study and analyze some properties of Directed Graphs.
Fact 1: if there are at least two vertices in the graph with an exit degree of 0, then no vertex is the most popular, that is, the answer is 0.
Apparently, if the directed graph has a ring, the cows on the ring agree that if C can be reached by a point on the ring, it is bound to be reached by any other point on the ring.
Fact 2: the opinions of the cows on each strongly connected subgraph are consistent.
Therefore, in this question, we can regard every strongly connected subgraph (and the dairy herd it represents) as a whole. If we regard each strongly connected subgraph as a super vertex that can compress all vertex contraction from all vertices of the subgraph to obtain a new super graph, it is easy to prove that,
Fact 3: A supergraph is a directed acyclic graph (DAG ).
The degree of output of a strongly connected subgraph is defined as the degree of output of its super Vertex on the Super Graph, its neighbor is the strongly connected subgraph corresponding to the neighbor of its super Vertex on the Super Graph. If the output degree of a strongly connected subgraph is 0, it is calledSink). As we can see from facts, if there are at least two concurrencies on the Super Graph, no cows are the most popular. So far, with fact 1, we can quickly give answers when there are no most popular cows. However, if the graph is not aggregated, the fact is useless, and we cannot see how the other two facts can be used to improve the algorithm. However, the following facts bring us hope.
Fact 4: Any finite Dag has at least one sink.
This fact is not too obvious, just add it to prove it. Use the reverse verification method. Suppose there is no remittance. All vertices have at least one outbound edge, that is, at least one neighbor. Now, let's take a bit of V1. Starting from V1, any neighbor V2. Since each vertex has an outbound edge, this process can be performed to obtain the path V1, V2,..., vn + 1, where N is the number of vertices of the graph. Because there are n + 1 vertices on the path, there must be at least two vertices. The vi, vi + 1 ,..., VJ forms a ring, which is in conflict with the figure Dag. Pass.
Because there is at least one sink in the super graph, the sink is the vertex with a degree of 0, that is, it thinks that other dairy clusters are not welcome. Therefore,If a vertex is not a sink, it cannot be the most popular! Therefore, we only need to consider the sink on the original graph. Based on Fact 1, we can consider at most one sink, because when there are at least two sinks, the answer is 0. Based on the above discussion, the following algorithms can be designed:
Find each strongly connected subgraph of the source image. <br/> Find the Super Graph of the source image. <br/> Find all the maps of the Super Graph. <br/> if there are at least two maps, 0 is output. <br/> otherwise, it determines whether the sink can be reached by all other super vertices. If yes, the number of vertices of the strongly connected subgraph corresponding to the sink is output. Otherwise, 0 is output. <Br/>
Both step 1 and Step 2 only require O (V + e) Time, and step 3 only requires O (V). For Step 5, you can) first reset the super graph, and then check whether the vertex can reach all other vertices through the side of the transpose Super Graph. This also requires O (V + E ). Therefore, the total time complexity is O (V + E ).
At this point, the question is well answered. However, it is not perfect. The above algorithms require strongly connected subgraphs, supergraphs, and even transpose super graphs! This requires you to scan the source image and super image multiple times, and search for the source image and super image multiple times in depth first! This seems unacceptable for perfectionists. Although there is no way to reduce the time complexity, we can try to reduce the Constant Coefficient of the complexity and make the computation elegant and easy to implement.
First, the fifth step is the most eye-catching. In this step, you need to transpose the Super Graph and perform a deep first search on the transpose Super Graph. Can you remove this step? That is, if there is a unique sink on the Dag, is there a quick way to determine whether the sink is the most popular? Now let's look at the most beautiful conclusion in this question.
Fact 5: If a finite Dag has only one sink, the sink can be reached by any other vertex.
This fact is not obvious, so we need to prove it briefly. Use the reverse verification method. Assume that the source image G has at least one vertex u and cannot reach the sink T. Divide all vertices in the graph into two types. The first class contains t and all vertices that can reach t; the second class cannot reach T. Obviously, the first class has at least vertex t, and the second class has at least vertex u, so they are not empty. Therefore, all vertices in the second class constitute a non-empty subgraph G', And the subgraph is also a dag. Therefore, from fact 4, there is at least one sink s, that is, S has no edge to any vertex in the second vertex. We assert that S is also a collection of G. This is because s cannot be connected to any vertex v in the first class. Otherwise, S-> V --> T (S-> V indicates that there is an edge from S to v, V --> T indicates that there is a path from V to T) as a path from S to T, which is in conflict with s as the second vertex. Therefore, S has no edge pointing to any other vertex in G, that is, S is a sink of G. However, this is in conflict with only one sink of G. Therefore, if it is not true, no vertex u cannot reach the sink T, that is, t can be reached by any other vertex.
In this way, we can save Step 5. In the remaining four steps, the most important thing is whether the output degree of a strongly connected subgraph is 0. By modifying the Tarjan Algorithm for strongly connected subgraphs, you can judge whether the output degree of the strongly connected subgraphs obtained is 0 in the depth-first search. In this way, we do not need to create a super image of the source image, so that we only need to perform a deep-first search to solve this problem. In this way, the question is a perfect answer.
Algorithm night fish is <br/> input: Graph G = (V, E) <br/> output: the number of popular cows <br/> index: = 0 <br/> S: = empty <br/> sink_count: = 0 // The number of sinks <br/> popular_count: = undefined // The number of popular cows <br/> for each V in V do <br/> If (v. index is undefined and popular_count is not zero) <br/> strongconnect (V) <br/> end if <br/> repeat <br/> output popular_count <br/> procedure strongconnect (V) <br/> // set the depth index for V to the smallest unused index <br/> v. index: = index <br/> v. lowlink: = index <br/> index: = index + 1 <br/> S. push (v) <br/> v. out_flag: = false // indicate if V is connected to other SCC <br/> // consider successors of v <br/> for each (V, W) in e do <br/> If (W. index is undefined and popular_count is not zero) Then <br/> // successor W has not yet been visited; recurse on it <br/> strongconnect (W) <br/> v. lowlink: = min (v. lowlink, W. lowlink) <br/> else if (W is in S) Then <br/> // successor W is in stack S and hence in the current SCC <br/> v. lowlink: = min (v. lowlink, W. index) <br/> else <br/> v. out_flag: = true <br/> end if <br/> repeat <br/> // If V is a root node, pop the stack and generate an SCC <br/> If (v. lowlink = v. index) Then <br/> v. scc_id: = any unused SCC id <br/> scc_size: = 0 // the size of this SCC <br/> repeat <br/> W: = S. pop () <br/> W. scc_id: = v. scc_id <br/> scc_size: = scc_size + 1 <br/> v. out_flag: = v. out_degree or W. out_flag <br/> until (W = V) <br/> If v. out_flag = true then <br/> sink_count: = sink_count + 1 <br/> popular_count: = scc_size <br/> end if <br/> If sink_count> 1 then <br/> popular_count: = 0 <br/> end if <br/> end procedure
Summary: Some questions require in-depth mining to find beautiful solutions, while some mathematical theories and properties often play a role in the in-depth mining process. This is an example. This type of problem is also my favorite one: by analyzing the nature of the question and combining some mathematical theories, we can find an elegant and beautiful solution.