NYOJ-城市平乱-115

城市平乱

时间限制:1000 ms | 内存限制:65535 KB
难度:4

描述

南将军统领着N个部队,这N个部队分别驻扎在N个不同的城市。

他在用这N个部队维护着M个城市的治安,这M个城市分别编号从1到M。

现在,小工军师告诉南将军,第K号城市发生了暴乱,南将军从各个部队都派遣了一个分队沿最近路去往暴乱城市平乱。

现在已知在任意两个城市之间的路行军所需的时间,你作为南将军麾下最厉害的程序员,请你编写一个程序来告诉南将军第一个分队到达叛乱城市所需的时间。

这里写图片描述

注意,两个城市之间可能不只一条路。

输入

第一行输入一个整数T,表示测试数据的组数。(T<20)
每组测试数据的第一行是四个整数N,M,P,Q(1<=N<=100,N<=M<=1000,M-1<=P<=100000)其中N表示部队数,M表示城市数,P表示城市之间的路的条数,Q表示发生暴乱的城市编号。
随后的一行是N个整数,表示部队所在城市的编号。
再之后的P行,每行有三个正整数,a,b,t(1<=a,b<=M,1<=t<=100),表示a,b之间的路如果行军需要用时为t

数据保证暴乱的城市是可达的。

输出

对于每组测试数据,输出第一支部队到达叛乱城市时的时间。每组输出占一行

样例输入

1
3 8 9 8
1 2 3
1 2 1
2 3 2
1 4 2
2 5 3
3 6 2
4 7 1
5 7 3
5 8 2
6 8 2

样例输出

4

这就是一个的寻路算法,这里只需要将暴乱的城市设为开始城市时间就是权值,遍历完所有的城市之后在有部队的城市找最小值,然后输出这个城市的编号。我的寻路算法用的是SPFA算法
全部代码如下

//#include<bits/stdc++.h>
#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<string>
#include<iterator>
#include<queue>
#include<string.h>
using namespace std;
#define MAX  1005

int N, M, P, Q;
int dis[MAX][MAX], trop[MAX];
int spfa(int s)
{
    queue<int> que;//没有遍历的城市入队
    int city[MAX] = { 0 }, path[MAX] = { 0 }, visit[MAX] = { 0 },smin = 0;
    memset(path, 2, sizeof(path));//将初始值最大化
    que.push(s);path[s] = 0;visit[s] = 1;//将第一个城市入队同时访问状态设为1
    while (!que.empty())
    {
        int temp = que.front();que.pop();//取出头结点的城市
        for (int i = 1;i <= M;i++)
        {
            if (path[temp] + dis[temp][i]<path[i])//路径进行松弛操作更新为最短
            {
                path[i] = path[temp] + dis[temp][i];
                if (!visit[i])//如果没有被访问就入队
                {
                    que.push(i);
                    visit[i] = 1;
                }
            }
            if (trop[i] == 1)
            {
                smin = (smin != 0 ? smin : path[i]) < path[i] ? smin : path[i];//找最短的时间
            }
        }
    }
    cout << smin << endl;
    return 0;
}
int main()
{
    freopen("data.in", "r", stdin);
    int t;
    cin >> t;
    while (t--)
    {
        memset(dis, 2, sizeof(dis));
        memset(trop, 0, sizeof(trop));
        cin >> N >> M >> P >> Q;
        for (int i = 0;i < N;i++)
        {
            int num;
            cin >> num;
            trop[num] = 1;
        }
        for (int i = 0;i < P;i++)
        {
            int a, b, t;
            cin >> a >> b >> t;
            if (dis[a][b] > t)
            {
                dis[a][b] = dis[b][a] = t;//虽然两个城市之间路径不止一条 只需要存入时间最短的一条
            }
        }
        spfa(Q);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值