重要人物(最短路)

题目描述
某重要人物P要寻访城市C的G个地方,由于该人物非常重要,交警打算对人物P行走的街道进行临时封道(不准普通市民进入,但如果在封道前进入的可以继续行走,也可以正常出去)。当人物P进入这条街道之前和P走出这条街道之后,普通市民都可以正常进入该街道。
比如,P在第10分钟期间进入街道X,并要X街道上行走5分钟,则在第10、11、12、13、14分钟期间,普通市民不可以进入X街道,市民可以在第9分钟之前(含第9分钟)进入,也可以在第15分钟之后(含第15分钟)进入。
人物P寻访K分钟后,有一市民S打算从城市的A处到达B处,请编程计算P从A到B的最少用时。注意:市民S在行走的过程中某条街道可以走,但为了用更短的时间,可以选择等待!

输入
共M+3行。
第1行2个整数N 和 M (2 ≤ N ≤ 1000, 2 ≤ M ≤ 10 000),分别表示城市中的结点(即某个地方,从1到N编号)的数量以及街道的数目。
第2行包含4个整数A, B, K 和 G (1≤A,B≤N, 0≤K≤1000, 0≤G≤1000),分别表示:
市民S的出发地
市民S的目的地
市民S是在人物P寻访K分钟后开始出发
人物P寻访的结点(地方)数量
第3行G个整数,表示人物P将要寻访的G处地方的编号,每一对结点代表了人物P寻访要经过的街道,每条街道仅走一次。
接下来M行,每行3个整数A, B 和 L(1 ≤ A, B ≤ N, 0 ≤ L ≤ 1000),表示A和B之间有一条需要走L分钟的街道(假定人物P和市民S行走速度相同)。

输出
包含1行,表示市民S从A处到达B处的最少用时(单位分钟)。

样例输入
【样例1】
6 5
1 6 20 4
5 3 2 4
1 2 2
2 3 8
2 4 3
3 6 10
3 5 15
【样例2】
8 9
1 5 5 5
1 2 3 4 5
1 2 8
2 7 4
2 3 10
6 7 40
3 6 5
6 8 3
4 8 4
4 5 5
3 4 23

样例输出
【样例1】
21
【样例2】
40

提示
40%的数据保证2 ≤ N ≤ 550且2 ≤ M ≤ 4000
100%的数据保证2 ≤ N ≤ 1000且2 ≤ M ≤ 10000

思路
根据题意,找封闭路段的每一个时间间隔,在考虑时间间隔的基础上跑最短路即可,注意双向边同时建立时间间隔

代码实现

#pragma GCC optimize(3,"Ofast","inline")
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int N=1005;
const int M=10005;
const int INF=0x3f3f3f;
const ull sed=31;
const ll mod=1e9+7;
const double eps=1e-9;
typedef pair<int,int>P;
typedef pair<double,double>Pd;

struct qnode
{
    int v,c;
    qnode(int _v=0,int _c=0):v(_v),c(_c){}
    bool operator < (const qnode &r) const
    {
        return c>r.c;
    }
};

struct node
{
    int to,index,w;
}E[M<<1];

int head[N],cnt,n,m;
int a,b,k,g;
int w[N];
int dis[N];
P vst[M<<1];
bool vis[N];

void add(int u,int v,int w)
{
    E[cnt].to=v;
    E[cnt].w=w;
    E[cnt].index=head[u];
    head[u]=cnt++;
}

void dji(int s)
{
    for(int i=1;i<=n;i++)
    {
        dis[i]=INF;
        vis[i]=false;
    }
    priority_queue<qnode>que;
    que.push(qnode(s,k));
    dis[s]=k;
    while(!que.empty())
    {
        qnode top=que.top();
        que.pop();
        int u=top.v;
        if(vis[u]) continue;
        vis[u]=true;
        for(int i=head[u];~i;i=E[i].index)
        {
            int v=E[i].to,cost=E[i].w;
            if(dis[u]<vst[i].first || dis[u]>vst[i].second)
            {
                if(!vis[v] && dis[v]>dis[u]+cost)
                {
                    dis[v]=dis[u]+cost;
                    que.push(qnode(v,dis[v]));
                }
            }
            else
            {
                if(!vis[v] && dis[v]>vst[i].second+cost+1)
                {
                    dis[v]=vst[i].second+cost+1;
                    que.push(qnode(v,dis[v]));
                }
            }
        }
    }
}

void dfs(int x,int tot,int t)
{
    if(tot==g) return ;
    for(int i=head[x];~i;i=E[i].index)
    {
        int v=E[i].to,cost=E[i].w;
        if(v==w[tot+1])
        {
            vst[i]=P(t,t+cost-1);
            vst[i^1]=P(t,t+cost-1);
            dfs(v,tot+1,t+cost);
        }
    }
}
int main()
{
    memset(head,-1,sizeof(head));
    scanf("%d%d",&n,&m);
    scanf("%d%d%d%d",&a,&b,&k,&g);
    for(int i=0;i<g;i++) scanf("%d",&w[i]);
    for(int i=0;i<m;i++)
    {
        int u,v,w;
        scanf("%d%d%d",&u,&v,&w);
        add(u,v,w);add(v,u,w);
    }
    dfs(w[0],0,0);
    dji(a);
    printf("%d\n",dis[b]-dis[a]);
    return 0;
}

发布了235 篇原创文章 · 获赞 13 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/weixin_43935894/article/details/104199615