检查仅 S 和 T 重复的无向图中节点 S 和 T 之间是否存在循环
给定一个有N个节点和两个顶点S & T的无向图,任务是检查这两个顶点之间是否存在循环,使得除了S和T之外的其他节点在该循环中出现的次数不超过一次。如果存在则打印Yes ,否则打印No。
例子:
Input: N = 7, edges[][] = {{0, 1}, {1, 2}, {2, 3}, {3, 4}, {4, 5}, {5, 2}, {2, 6}, {6, 0}}, S = 0, T = 4
Output: No
Explanation:
Node 2 appears two times, in the only cycle that exists between 0 & 4
Input: N = 6, edges[][] = {{0, 1}, {0, 2}, {2, 5}, {3, 1}, {4, 5}, {4, 3}}, S = 0, T = 3
Output: Yes
Explanation:
Cycle between 0 and 3 is: 0->1->3->4->5->2->0
方法:
如果存在一条从 T 到 S 的路径,该路径没有用于从 S 到 T 的路径的任何顶点,则将始终存在一个循环,使得除S和T之外的其他节点不会出现多次。现在,要解决问题,请按照以下步骤操作:
- 制作一个大小为n的数组(其中 n 是节点数),并将其初始化为全 0。
- 从S开始深度优先搜索,并将T作为目的地。
- 将当前节点的值0更改为1,在visited数组中,以跟踪该路径中访问的节点。
- 如果无法达到T ,那么它们之间就不可能存在简单的循环。所以,打印号。
- 如果达到T ,则将目的地更改为S并继续深度优先搜索。现在,除了S之外,已经访问过的节点不能再次访问。
- 如果达到S ,则打印Yes,否则打印No。
下面是上述方法的实现:
C++
// C++ program for the above approach
#include
using namespace std;
// Function to create graph
void createGraph(vector >& graph,
vector >& edges)
{
for (auto x : edges) {
// As it is an undirected graph
// so add an edge for both directions
graph[x[0]].push_back(x[1]);
graph[x[1]].push_back(x[0]);
}
}
bool findSimpleCycle(int cur,
vector >& graph,
int start, int dest,
vector& visited,
bool flag)
{
// After reaching T, change the dest to S
if (!flag and cur == dest) {
dest = start;
flag = 1;
}
// If S is reached without touching a
// node twice except S and T,
// then return true
if (flag and cur == dest) {
return true;
}
bool ans = 0;
visited[cur] = 1;
for (auto child : graph[cur]) {
// A node can only be visited if it
// hasn't been visited or if it
// is S or t
if (!visited[child] or child == dest) {
ans = ans
| findSimpleCycle(
child, graph, start,
dest, visited, flag);
}
}
// Change visited of the current node
// to 0 while backtracking again so
// that all the paths can be traversed
visited[cur] = 0;
return ans;
}
int main()
{
int nodes = 7;
vector > edges
= { { 0, 1 }, { 1, 2 }, { 2, 3 },
{ 3, 4 }, { 4, 5 }, { 5, 2 },
{ 2, 6 }, { 6, 0 } };
int S = 0, T = 4;
// To store the graph
vector > graph(nodes);
// To keep track of visited nodes
vector visited(nodes);
createGraph(graph, edges);
// If there exists a simple
// cycle between S & T
if (findSimpleCycle(S, graph,
S, T, visited, 0)) {
cout << "Yes";
}
// If no simple cycle exists
// between S & T
else {
cout << "No";
}
}
Python3
# Function to create graph
def createGraph(edges, N):
graph = list([] for _ in range(N))
for node1, node2 in edges:
# As it is an undirected graph,
# add an edge for both directions
graph[node1].append(node2)
graph[node2].append(node1)
return graph
def findSimpleCycle(cur,
graph,
start, dest,
visited,
flag):
# After reaching T, change the dest to S
if ((not flag) and cur == dest):
dest = start
flag = True
# If S is reached without touching a
# node twice except S and T,
# then return true
if (not flag and cur == dest):
return True
# first guess is that there is no cycle
# so ans is False.
# if we find one cycle, ans will be true
# and then returned .
ans = False
# mark node as visited in this path
visited[cur] = True
for child in graph[cur]:
# A node can only be visited if it
# hasn't been visited or if it
# is S or t
if (not visited[child]) or child == dest:
ans = ans or findSimpleCycle(
child, graph, start,
dest, visited, flag)
# Change visited of the current node
# to 0 while backtracking again so
# that all the paths can be traversed
visited[cur] = False
return ans
if __name__ == "__main__":
N = 7 # number of nodes
edges = [[0, 1], [1, 2], [2, 3],
[3, 4], [4, 5], [5, 2],
[2, 6], [6, 0]]
S = 0
T = 4
# To keep track of visited nodes
visited_array = list(False for _ in range(N))
# If there exists a simple
# cycle between S & T
if (findSimpleCycle(cur=S, graph=createGraph(edges, N),
start=S, dest=T,
visited=visited_array,
flag=0)):
print("Yes")
# If no simple cycle exists
# between S & T
else:
print("No")
Javascript
No
时间复杂度: O(N!)。正如我们在这个算法中看到的,所有路径都可以遍历,在最坏的情况下,我们将遍历所有路径以找到有效的路径,请参阅这篇文章:https://www.geeksforgeeks.org/count-possible-路径-两个-顶点/
辅助空间: O(N^2)