Traffic jam FZU - 2298

Xzz is a child with severe procrastinations. The new semester begins, He still has a lot of homework to do. Now, he needs your help. As the best friend, you are good at math. So, you will help him do some math homework. Now Xzz wants to go to your home. You can regard the traffic network as a undirected graph with n nodes (numbered from 1 to n) and m edges.

Xzz’s home at node s, and your at node t. At each node i, there is a traffic light, and the traffic light change the status after ai, which means that you can only leave node i, at time[0, ai), [2 * ai, 3 * ai), [4 * ai, 5 * ai), … , [2k * ai, (2 * k + 1) * ai). If ai = 0 means there is no traffic light, you can leave at any time. And there are m edges, each edge means it will take Xzz vi time from node xi to node yi. Now Xzz wants to know how much time he will take to arrive your home.

Input

First line of the input file contains an integer T(0 < ≤ 20) that indicates how many cases of inputs are there.

The description of each case is given below:

The first line of each case contains two numbers n, m, means there are n nodes and m edges.

(n ≤ 1000, m ≤ n(n-1) / 2)

Then follow n lines. In ith line there will be a number, ai.(ai ≤ 1000)

Then follow m lines. In ith line there will be three numbers, xi, yi and vi, means there is a edge between xi and yi, and Xzz take vi time to go trough this edge. vi ≤ 1000.

The last line contains two numbers s, t. It’s guarantee that there is at least one path between node s and t.

Output

One integer means the minimum time Xzz go to node t.

Sample Input

1
9 14
3
5
7
3
5
7
9
3
5
1 2 4
1 8 8
2 3 8
2 8 11
3 4 7
3 6 4
3 9 2
4 5 9
4 6 14
5 6 10
6 7 2
7 9 6
7 8 1
8 9 7
1 5

Sample Output

28

题意:开始的 n 行是 每个点的a[i] 值 代表的是红灯的时间,接下来m 行给出三个数 a,b,c 带表示a 到  b 有一条双向边 所花费的时间为c ,  接下来有两个数 s ,t  s 是起点 ,t 是终点, 问从s 到 t 的最小时间是什么。

思路:该题目属于最短路问题,如果k= (到当前路口的总时间 /  该路口的红绿灯周期),如果结果为基数,那么就代表可以直接通过,否则,等待时间就是  delay = (k+1)*tim[i]-(dis[mid]+mp[mid][i]), 注意 如果tim[i]==0 那么delay=0,如果当前位置为终点  t  ,那么delay =0。 开始没有用优先队列进行优化 ,导致一直WA 后来改成堆优化过了,现在想想应该是维护时间时出错了。。。

代码如下:

#include<stdio.h>
#include<algorithm>
#include<iostream>
#include<string.h>
#include<queue>
#define ll long long
using namespace std;
const int maxn=1005;
const ll INF =1ll<<30;
int mp[maxn][maxn];
int tim[maxn];
int dis[maxn];
bool vis[maxn];
int n,m;
int Start,End;
struct Node
{
    int id;
    int data;
    friend bool operator <(Node A, Node B) 
    {
        return A.data > B.data;
    }
};
void init()
{
    for(int i=1; i<=n; i++)
    {
        for(int j=1; j<=n; j++)
        {
            if(i==j)mp[i][j]=0;
            else mp[i][j]=INF;
        }
    }
    for(int i=1;i<=n;i++)dis[i]=INF;
    memset(vis,false,sizeof(vis));
}
void Dijkstra(int s)
{
    priority_queue<Node>q;
    while(!q.empty())q.pop();
    Node a;
    a.data=0;
    a.id=s;
    dis[s]=0;
    q.push(a);
    while(!q.empty())
    {
        Node now =q.top();
        q.pop();
        int mid=now.id;
        if(vis[mid])continue;
        vis[mid]=true;
        for(int i=1;i<=n;i++)
        {
            if(!vis[i])
            {
                int delay=0;
                int k=(dis[mid]+mp[mid][i])/tim[i];
                if(k%2!=0)delay = (k+1)*tim[i]-(dis[mid]+mp[mid][i]);
                else delay=0;
                if(i==End)delay=0;
                if(tim[i]==0)delay = 0;
                if(dis[i]>dis[mid]+mp[mid][i]+delay)
                {
                    dis[i]=dis[mid]+mp[mid][i]+delay;
                    Node p;
                    p.data=dis[i];
                    p.id=i;
                    q.push(p);
                }
            }
        }
    }
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&n,&m);
        init();
        for(int i=1; i<=n; i++)scanf("%d",&tim[i]);
        for(int i=0; i<m; i++)
        {
            int a,b,c;
            scanf("%d%d%d",&a,&b,&c);
                mp[a][b]=mp[b][a]=c;
        }
        scanf("%d%d",&Start,&End);
        Dijkstra(Start);
//        for(int i=1; i<=n; i++)
//        {
//            printf("%d ",dis[i]);
//        }
//        printf("\n");
        printf("%d\n",dis[End]);
    }
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值