00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #include "graph/connectivity.h"
00015
00016 #include <algorithm>
00017 #include <vector>
00018
00019 #include "base/logging.h"
00020
00021 namespace operations_research {
00022
00023 void ConnectedComponents::Init(NodeIndex min_index, NodeIndex max_index) {
00024 CHECK_LT(1, max_index - min_index);
00025 CHECK_LE(0, min_index);
00026 min_index_ = min_index;
00027 max_index_ = max_index;
00028 class_.Reserve(min_index, max_index);
00029 class_size_.Reserve(min_index, max_index);
00030 for (NodeIndex node = min_index; node <= max_index; ++node) {
00031 class_.Set(node, node);
00032 }
00033 class_size_.SetAll(1);
00034 }
00035
00036 void ConnectedComponents::AddArc(NodeIndex tail, NodeIndex head) {
00037 max_seen_index_ = std::max(max_seen_index_, tail);
00038 max_seen_index_ = std::max(max_seen_index_, head);
00039 NodeIndex tail_class = CompressPath(tail);
00040 NodeIndex head_class = CompressPath(head);
00041 if (tail_class != head_class) {
00042 MergeClasses(tail_class, head_class);
00043 }
00044 }
00045
00046 void ConnectedComponents::AddGraph(const StarGraph& graph) {
00047 Init(StarGraph::kFirstNode, graph.num_nodes());
00048 for (StarGraph::ArcIterator arc_it(graph); arc_it.Ok(); arc_it.Next()) {
00049 const ArcIndex arc = arc_it.Index();
00050 AddArc(graph.Tail(arc), graph.Head(arc));
00051 }
00052 max_seen_index_ = graph.num_nodes() - 1;
00053 }
00054
00055 NodeIndex ConnectedComponents::CompressPath(NodeIndex node) {
00056 DCHECK_LE(min_index_, node);
00057 DCHECK_GE(max_index_, node);
00058 while (node != class_[node]) {
00059 DCHECK_LE(min_index_, class_[node]);
00060 DCHECK_GE(max_index_, class_[node]);
00061 DCHECK_LE(min_index_, class_[class_[node]]);
00062 DCHECK_GE(max_index_, class_[class_[node]]);
00063 class_.Set(node, class_[class_[node]]);
00064 node = class_[node];
00065 }
00066 return node;
00067 }
00068
00069 NodeIndex ConnectedComponents::GetClassRepresentative(NodeIndex node) {
00070 DCHECK_LE(min_index_, node);
00071 DCHECK_GE(max_index_, node);
00072 NodeIndex representative = node;
00073 while (class_[representative] != representative) {
00074 representative = class_[representative];
00075 }
00076
00077
00078
00079 class_.Set(node, representative);
00080 return representative;
00081 }
00082
00083 NodeIndex ConnectedComponents::GetNumberOfConnectedComponents() {
00084 std::vector<bool> seen(max_index_);
00085 NodeIndex number = 0;
00086 for (NodeIndex node = min_index_; node <= max_seen_index_; ++node) {
00087 NodeIndex representative = GetClassRepresentative(node);
00088 if (!seen[representative]) {
00089 seen[representative] = true;
00090 ++number;
00091 }
00092 }
00093 return number;
00094 }
00095
00096 void ConnectedComponents::MergeClasses(NodeIndex node1, NodeIndex node2) {
00097
00098
00099 DCHECK_LE(min_index_, node1);
00100 DCHECK_GE(max_index_, node1);
00101 DCHECK_LE(min_index_, node2);
00102 DCHECK_GE(max_index_, node2);
00103 if (class_size_[node1] < class_size_[node2]) {
00104 std::swap(node1, node2);
00105 }
00106 class_.Set(node2, node1);
00107 class_size_.Set(node1, class_size_[node1] + class_size_[node2]);
00108 }
00109
00110 }