#include <iostream>
#include <vector>
#include <map>
#include <set>
#include <list>
template<typename T>
struct NodeInfo
{
std::set<T> source;
};
template<typename T>
bool checkSameCircle(std::list<T>& circle1, std::list<T>& circle2)
{
if (circle1.size() != circle2.size())
return false;
auto iter = std::find(circle2.begin(), circle2.end(), circle1.front());
if (iter == circle2.end())
return false;
for (auto data : circle1) {
if (data != *iter++) {
return false;
}
if (iter == circle2.end())
iter = circle2.begin();
}
return true;
}
template<typename T>
void checkDest(std::vector<std::list<T>>& result, const std::map<T, NodeInfo<T>>& info, T source, std::list<T>& dest)
{
dest.push_front(source);
for (auto s : info.at(source).source) {
if (std::find(dest.begin(), dest.end(), s) != dest.end()) { // circled
if (dest.back() != s)
continue;
bool sameCircle = false;
for (auto lst : result) {
if (sameCircle = checkSameCircle(lst, dest))
break;
}
if (sameCircle)
continue;
result.push_back(dest);
}
else {
checkDest(result, info, s, dest);
}
}
dest.pop_front();
}
template<typename T>
std::vector<std::list<T>> findCircles(const std::vector<std::pair<T, T>>& graph)
{
std::vector<std::list<T>> result;
std::map<T, NodeInfo<T>> info;
for (auto& [source, dest] : graph) {
if (source == dest)
result.push_back({ dest, dest });
else
info[dest].source.insert(source);
}
std::list<T> dest;
for (auto iter : info) {
T node = iter.first;
checkDest(result, info, node, dest);
}
return result;
}
int main()
{
std::vector<std::pair<int, int>> graph = {
{1, 2},
{1, 3},
{2, 4},
{3, 4},
{4, 5},
{5, 1},
{4, 1},
{1, 1},
};
auto result = findCircles(graph);
for (auto& lst : result) {
for (auto node : lst) {
std::cout << node << "->";
}
std::cout << lst.front() << std::endl;
}
}
输出结果:
1->1->1
2->4->1->2
3->4->1->3
2->4->5->1->2
3->4->5->1->3