SGU103 最短路 Shortest Path

    题意:一个带权无向图,每个点有一个只有两种颜色的指示灯,每个灯初始颜色维持一定时间T1后变色,之后经过T2时间变色、T3时间变色、T2时间再变……成周期。一条边只有两个端点的指示灯颜色相同时才能通过,否则要等到相同。问从1到N的最短时间花费以及路径方案。

    Problem:Give you a weighted undirected graph, each node has a traffic light with only two colors. Each light will change it's original color after T1 time, then it comes to a period - after T2, T3, T2 ……it changes color. Only when the two nodes of an edge change into the same color, can one pass through the edge. If it is not the case one must wait for it. You should give a solution which cost the least time from node 1 to N if there exist one.

    解法:首先gettime(x,y,t)求在t时刻到达x点,需要等候多长时间能到y点。求出这个后,加在最短路算法的费用上即可。需注意有的边永远无法通过。求gettime,先算出t时刻两个灯什么颜色,再模拟三个来回,因为只要周期不同,三次变色内两灯就能同色。

    Solution:First use function gettime(x,y,t) to calculate how much time you need to wait when you reach node x at time t and you want to go node y next. After that, you just need to add this on the cost of Shortest Path Algorithm. Note that some edges are not access forever. When you calculate gettime(), you should figure out what colors of the two lights at time t, then simulate the process for 3 times, cause in 3 time the lights will change into the same color if their periods is not totally same.  

    

#include <iostream>
#include <stdio.h>
#include <cstring>
#include <queue>
using namespace std;
#define N 400
#define M 15000
#define inf 1010001000
struct gtype {
       int to,next,w;
}g[2*M];
struct data {
       int c,r,b,p;
}p[N];
int tot,first[N],dis[N],his[N],ans[N],st,ed;
int n,m,x,y,w;
bool v[N];
void add(int x,int y,int w) {
     tot++;
     g[tot].to = y;
     g[tot].w = w;
     g[tot].next = first[x];
     first[x] = tot;
}
int gettime(int x,int y,int t) {
    if (p[x].b+p[x].p==0) return -1;
    if (p[y].b+p[y].p==0) return -1;
    int r1 = p[x].r-t, t1 = p[x].c;
    int r2 = p[y].r-t, t2 = p[y].c;
    if (t>=p[x].r) {
       int tt = (t-p[x].r)%(p[x].b+p[x].p);
       if ((t1==0 && tt<p[x].p) || (t1==1 && tt<p[x].b)) {
          if (t1==0) r1 = p[x].p - tt;
          else r1 = p[x].b - tt;
          t1 ^= 1;
       }
       else r1 = p[x].b+p[x].p-tt;
    }
    if (t>=p[y].r) {
       int tt = (t-p[y].r)%(p[y].b+p[y].p);
       if ((t2==0 && tt<p[y].p) || (t2==1 && tt<p[y].b)) {
          if (t2==0) r2 = p[y].p - tt;
          else r2 = p[y].b - tt;
          t2 ^= 1;
       }
       else r2 = p[y].b+p[y].p-tt;
    }
    if (t1==t2) return 0;
    if (t1==1) {
       swap(r1,r2);
       swap(x,y);
    }
    int q1[3];
    int q2[3];
    q1[0] = r1;
    q1[1] = p[x].p + q1[0];
    q1[2] = p[x].b + q1[1];
    q2[0] = r2;
    q2[1] = p[y].b + q2[0];
    q2[2] = p[y].p + q2[1];
    for (int i=0;i<3;i++)
        if (q1[i]!=q2[i]) return min(q1[i],q2[i]);
    return -1;
}
int spfa() { 
     memset(v,0,sizeof(v));
     for (int i=1;i<=n;i++) dis[i] = inf; 
     queue <int> q;
     q.push(st);
     v[st] = true;
     dis[st] = 0;
     while (!q.empty()) {
           int x = q.front();
           v[x] = false;
           q.pop();
           for (int t=first[x];t!=-1;t=g[t].next) {
               int y = g[t].to;
               int tt = gettime(x,y,dis[x]);
               if (tt!=-1) {
                  if (dis[y] > dis[x] + g[t].w + tt) {
                     dis[y] = dis[x] + g[t].w + tt;
                     his[y] = x;
                     if (!v[y]) {
                        v[y] = true;
                        q.push(y);
                     }
                  }
               }
           }
     }
     if (dis[ed]==inf) return 0;
     return dis[ed];
}
int main() {
    while (~scanf("%d%d",&st,&ed)) {
          tot = 0;
          memset(first,-1,sizeof(first));
          scanf("%d%d",&n,&m);
          getchar();
          for (int i=1;i<=n;i++) {
              char c = getchar();
              if (c=='B') p[i].c = 0;
              else p[i].c = 1;
              scanf("%d%d%d",&p[i].r,&p[i].b,&p[i].p);
              getchar();
          }
          for (int i=1;i<=m;i++) {
              scanf("%d%d%d",&x,&y,&w);
              add(x,y,w);
              add(y,x,w);
          }
          int tt = spfa();
          printf("%d\n",tt);
          if (tt!=0) {
             int cnt = 0;
             int now = ed;
             while (now!=st) {
                now = his[now];
                ans[++cnt] = now;
             }
             for (int i=cnt;i>=1;i--)
                 printf("%d ",ans[i]);
             printf("%d\n",ed);
          }
    }
    return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值