最短游览路线
时间限制:
10000ms
单点时限:
1000ms
内存限制:
256MB
描述
十一期间小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。
5 7 1 2 5 1 2 4 2 3 3 2 3 4 4 5样例输出
4
•包含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; }