面试练习题-BFS 最短路径

题目1539:师弟

时间限制:1 秒

内存限制:128 兆

特殊判题:否

提交:185

解决:33

题目描述:

开学了,GrassLand的新师弟也来了,于是GrassLand打算去路口接他,以表兄长之谊。
已知:
共有n个路口,n个路口间存在着m条道路,每条道路连接两个路口,道路有其各自的长度。
GrassLand和他的实验室在1号路口,而他的师弟在n号路口。
师弟沿着最短路径走向实验室,若有多于一条的最短路径,他会任意选择一条。
GrassLand不希望走的太远而浪费科研的时间,所以他至多只会离开实验室k个路口。
问题出现了,GrassLand并不知道他的师弟会选择哪条路径。所以他想知道,所有离开实验室不超过k个路口(即该路口和实验室可以由至多k条道路连接)的路口中,在师弟和实验室间任意一条最短路径上的路口个数(包括实验室所在的1号路口和师弟所在的n号路口)。

输入:

输入包含多组测试用例。
每组测试用例开头为三个整数n(2 <= n <= 1000),m(1 <= m <= 100000),k(0 <= k <= 1000)
接下去m行描述道路信息,每行三个整数a(1 <= a <= n),b(1 <= b <= n && b != a),c(1 <= c <= 1000),表示连接路口a和路口b的道路长度为c。
数据保证1号路口和n号路口间连通。

输出:

对于每组测试用例,输出一个整数,代表符合条件的路口个数。

样例输入:
4 3 2
1 2 1
2 3 1
3 4 1
4 3 1
1 2 1
2 3 1
3 4 1
4 4 1
1 2 3
1 3 2
2 4 2
3 4 3
样例输出:
3
2
3


#include <iostream>
#include <queue>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <vector>
using namespace std;
const int N = 1001;
 
class Node
{
public:
    int e, cost;
    Node(int n, int c)
    {
        e = n;
        cost = c;
    }
 
};
int n, m, k;
vector<Node> edges[N];
vector<Node>::iterator iter1;
vector<int>::iterator iter2;
bool canVisit[N];
 
//得到限制范围内的那些点,存储在canVisit中
void getK()
{
    queue<Node> q;
    Node start(1, 0);
    q.push(start);
    canVisit[1] = true;
    while (q.size() > 0)
    {
        Node n = q.front();
        q.pop();
        if (n.cost >= k)
            break;
        for (iter1 = edges[n.e].begin(); iter1 != edges[n.e].end(); iter1++)
        {
            if (!canVisit[iter1->e])
            {
                canVisit[iter1->e] = true;
                Node newNode(iter1->e, n.cost + 1);
                q.push(newNode);
            }
        }
    }
    //for (int i = 0; i <= n; i++)
    //  cout << canVisit[i] << ",";
    //cout << endl;
}
 
int dis1[N]; //正向
int dis2[N]; //逆向
 
//计算从点start到其他所有节点的最短距离
void bfs(int start, int * dis)
{
    queue<int> q;
    q.push(start);
    bool visit[N] ={ false };
    dis[start]=0;
    while (q.size() > 0)
    {
        int e = q.front();
        q.pop();
        visit[e] = false;
        for (iter1 = edges[e].begin(); iter1 != edges[e].end(); iter1++)
        {
            //-1表示第一次到到改点
            if (dis[iter1->e] == -1 || dis[iter1->e] > dis[e] + iter1->cost)
            {
                dis[iter1->e] = dis[e] + iter1->cost;
                if (!visit[iter1->e])
                {
                    q.push(iter1->e);
                    visit[iter1->e] = false;
                }
            }
        }
    }
      // for(int i=0; i<=n; i++) cout << dis[i] << ",";
     //       cout << endl;
}
 
 
int main()
{
    int a,b,c;
 
    while (scanf ("%d%d%d",&n,&m,&k) != EOF)
    {
        memset(edges, 0, sizeof(edges));
        memset(canVisit, 0 ,sizeof(canVisit));
        memset(dis1, -1, sizeof(dis1));
        memset(dis2, -1, sizeof(dis2));
        for(int i=0; i<m; i++)
        {
            scanf("%d%d%d",&a,&b,&c);
            edges[a].push_back(Node(b,c));
            edges[b].push_back(Node(a,c));
        }
        getK();
        bfs(1,dis1);
        bfs(n,dis2);
        //dij(1,dis1);
        //dij(n,dis2);
        int ans=0;
        //统计最总结果
        for(int i=1; i<=n; i++){
            if(canVisit[i] && dis1[i] != -1 && dis2[i]!= -1){
                if(dis1[i] + dis2[i] == dis1[n])
                    ans++;
            }
        }
        printf("%d\n",ans);
    }
    return 0;
}





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值