方法一:拓扑排序加搜索
class Solution {
public:
bool vis[100005];
vector<int>v[100005];
int dfs(vector<int> &dist,int st,int step)
{
vis[st]=true;
// cout<<st<<endl;
int res=0;
for(int i=0;i<v[st].size();i++)
{
int x=v[st][i];
if(!vis[x] && dist[x]>0)
{
dist[x]--;
res=dfs(dist,x,step+1);
}
else if(vis[x] && dist[x]==1)
{
dist[x]--;
return step;
}
}
return res;
}
int longestCycle(vector<int>& edges) {
int n=edges.size();
memset(vis,false,sizeof(vis));
vector<int>dist(n,0);
for(int i=0;i<edges.size();i++)
{
if(edges[i]!=-1)
{
v[i].push_back(edges[i]);
dist[edges[i]]++;
}
}
//bfs去掉不在环里的点
queue<int>que;
for(int i=0;i<edges.size();i++)
{
if(dist[i]==0)
{
que.push(i);
}
}
while(!que.empty())
{
int st=que.front();
que.pop();
for(int i=0;i<v[st].size();i++)
{
int y=v[st][i];
dist[y]--;
if(dist[y]==0)
{
que.push(y);
}
}
}
queue<int>que1;
//只有环了,dfs搜素环的长度,取最大值
int res=0;
for(int i=0;i<n;i++)
{
if(dist[i]>0)
{
int num=dfs(dist,i,1);
// cout<<num<<endl;
res=max(res,num);
}
}
if(res==0) return -1;
return res;
}
};
方法二:内向基环树找环 + 利用时间戳简单实现
初始设置一个clock,记录每个点被访问的时间,当第二次访问到该点时,且第一次访问道该点的世时间大于开始时间,说明找到了一个环,用当前时间减去第一次访问到的时间即为环的长度。
class Solution {
public:
int longestCycle(vector<int>& edges) {
int n=edges.size();
int time[n];
int clock=1;
int res=0;
memset(time,0,sizeof(time));
for(int i=0;i<n;i++)
{
if(time[i])
{
continue;
}
int startTime;
for(int x=i,startTime=clock;x>=0;x=edges[x])
{
if(time[x])
{
if(time[x]>=startTime)
{
res=max(res,clock-time[x]);
}
break;
}
time[x]=clock++;
}
}
if(!res) res=-1;
return res;
}
};