最短游览路线
时间限制:
10000ms
单点时限:
1000ms
内存限制:
256MB
-
5 7 1 2 5 1 2 4 2 3 3 2 3 4 4 5
样例输出
-
4
描述
十一期间小Hi被朋友拉去某座名山旅游。这座山上一共有N个景点,编号1~N,通过M条单向缆车相连。
小Hi和朋友的出发点在1号景点。小Hi正在等待某公司的面试电话,所以他希望找一条路线,搭乘最少次数的缆车(至少一次),回到出发点。
你能求出最少搭乘缆车的次数吗?
输入
第一行包含两个整数N和M。
以下M行,每行包含两个整数a和b,代表有一条从a到b的单向缆车。
对于30%的数据,1 ≤ N ≤ 10, 1 ≤ M ≤ 90
对于100%的数据,1 ≤ N ≤ 10000, 1 ≤ M ≤ 100000, 1 ≤ a, b ≤ N, a ≠ b
输出
回到出发点最少搭乘缆车的次数。如果无法通过缆车回到出发点输出-1。
•包含1的环
–存在边j→1
–1→…→j的最短路为k
–环的长度为k+1
•深度优先搜索
–dfs(i,k),如果存在边i→1,则用k+1更新答案
–剪枝1:不重复的经过点
–剪枝2:当前路径长度+1超过最优值
DFS(深搜)--AC代码:
#include<bits/stdc++.h>
using namespace std;
int n,m;
vector<int > G[10010];//使用邻接表存储图
bool vis[10010];//标记数组
int minL;
void dfs(int s,int k)
{
if(k>=minL) return;//当前搜素的路径已经超过了前面的最优值,则回溯
for(int i=0;i<G[s].size();i++)
{
int r=G[s][i];
if(r==1)
{
minL=min(minL,k);//更新,这是判断邻接表下一步是否能走到起点位置
continue;
}
if(!vis[r])
{
vis[r]=1;
dfs(r,k+1);//搜索下一步
vis[r]=0;
}
}
}
int main()
{
while(scanf("%d%d",&n,&m)!=EOF)
{
for(int i=0;i<m;i++)
{
int x,y;
scanf("%d%d",&x,&y);
G[x].push_back(y);
}
minL=1<<30;
memset(vis,0,sizeof(vis));
vis[1]=1;
dfs(1,1);//传递的步数初始值为1,因为我们到终点的前一步就已经更新,默认这一步在搜索中未加
if(minL<(1<<30)) printf("%d\n",minL);
else printf("-1\n");
}
return 0;
}
BFS(广度优先搜索)--AC代码:
#include<bits/stdc++.h>
using namespace std;
int n,m;
vector<int>G[10010];
queue<int>qu;
bool vis[10010];
int ans,steps;
int main()
{
while(scanf("%d%d",&n,&m)!=EOF)
{
for(int i=0;i<m;i++)
{
int x,y;
scanf("%d%d",&x,&y);
G[x].push_back(y);
}
while(!qu.empty()) qu.pop();
qu.push(1);
bool flag=false;
memset(vis,0,sizeof(vis));
ans=1<<30;
steps=0;
while(!qu.empty())
{
int k=qu.size();
while(k--)
{
int t=qu.front();
qu.pop();
if(steps>0 && t==1)
{
ans=steps;
flag=true;
break;
}
for(int i=0;i<G[t].size();i++)
{
if(!vis[G[t][i]]) qu.push(G[t][i]);
}
}
steps++;
if(flag) break;
}
if(ans<(1<<30)) printf("%d\n",ans);
else printf("-1\n");
}
return 0;
}