题意:
给定n 个格子,m 条通道,并且每条通道只能走一次。
从1号格子出发,问能否回到 1 号格子。
若能回到 1 号格子则返回Yes,否则返回No。
方法一思路:根据题意建图,用邻接表存储。根据题意可知,是否存在包含三个节点的回路,其中一个节点是1号节点。
dfs
思路:
从1号格子开始dfs,深度遍历(一条路走到底),看是否还能回到1号格子。
用vis数组记录当前节点是否被访问过,一个节点只能被访问一次。
需要一个深度变量(depth)记录节点深度。
注意点:要添加判断条件,防止只包含两个节点的回路。
例如:1->2,2->1的回路。
class Solution
{
public:
string solve(vector<int>& param, vector<Point>& edge)
{
int n=param[0],m=param[1];//n个节点,m条边
vector<vector<int>> graph(n+1);//建图
vector<int> vis(n+1,0);//vis数组
for(int i=0;i<m;i++)//建立邻接表
{
int x=edge[i].x,y=edge[i].y;
graph[x].push_back(y);//无向图,双向
graph[y].push_back(x);
}
vis[1]=1;//标记1号节点已访问
if(dfs(1,vis,graph,0))//令1号节点深度为0
return "Yes";
else
return "No";
}
bool dfs(int x,vector<int> &vis,vector<vector<int>> graph,int depth)//查询是否包含1号节点的回路
{
int n=graph[x].size();
for(int i=0;i<n;i++)//遍历从节点x出发,所到达的节点y
{
int y=graph[x][i];
if(y==1&&depth!=1)//如果再次访问到1号节点(1号节点深度为0)并且当前节点深度不为1,则说明该回路不是两个节点构成的回路,即1->2,2->1的回路,则返回true
return true;
if(!vis[y])//未被访问的节点可以访问
{
vis[y]=1;
if(dfs(y,vis,graph,depth+1))//深度遍历,并且儿子节点深度+1
return true;
vis[y]=0;
}
}
return false;
}
};
时间复杂度:,n是节点数,m是边数,遍历每个节点和每条边。
空间复杂度:,n是节点数,最坏情况每两个节点都有边。
方法二
bfs
思路:
如果一个节点同时有两个不同的标记,则发生冲突,说明有回路。
vis数组不仅记录当前节点是否被访问过,而且还能充当节点的标记值。
class Solution
{
public:
string solve(vector<int>& param, vector<Point>& edge)
{
int n=param[0],m=param[1];//n个节点,m条边
vector<vector<int>> graph(n+1);//建图
vector<int> vis(n+1,0);//vis数组
for(int i=0;i<m;i++)//建立邻接表
{
int x=edge[i].x,y=edge[i].y;
graph[x].push_back(y);//无向图,双向
graph[y].push_back(x);
}
if(bfs(vis,graph))
return "Yes";
else
return "No";
}
bool bfs(vector<int> &vis,vector<vector<int>> graph)//查询是否包含1号节点的回路
{
int flag=2;
queue<int> q;
q.push(1);//1号节点入队列
vis[1]=1;//标记1号节点已访问(即已入队列),并且标记为1
while(!q.empty())
{
int x=q.front();//出队列
q.pop();
int n=graph[x].size();
for(int i=0;i<n;i++)//遍历x节点所延伸到的节点y
{
int y=graph[x][i];
if(vis[y]==0)//未访问的节点可以访问
{
if(x==1)
vis[y]=flag++;//如果是1号节点,则给1号节点的第一代儿子节点取不同编号(标记号从2开始),使得vis[y]!=0,也充当了已访问该节点的作用
else
vis[y]=vis[x];//否则跟随父节点的标记
q.push(y);
}
else if(vis[x]!=vis[y]&&y!=1)//调到这里说明y节点已访问,再判断如果y节点与x节点编号不一致并且子节点不是1号节点(即排除1->2,2->1的回路),则说明发生冲突,有回路
{
return true;
}
}
}
return false;
}
}; 时间复杂度:,n是节点数,m是边数,遍历每个节点和每条边。
空间复杂度:,n是节点数,最坏情况每两个节点都有边。



京公网安备 11010502036488号