• SGU 103 Traffic Lights


    SGU_103

        与一般的最短路问题不同的是,我们要首先判断什么时候才可以走上某条路,因此我们需要计算从当前这刻起两个灯变成相同颜色的最近的那一时刻,当然也有可能两灯根本不会变成相同的颜色,总体的一个思想就是如果两灯的一个最小公周期内没有出现相同的颜色,那么后面也一定不会出现相同的颜色。

        在计算等待时间的时候,可以依次枚举也可以一次性加到两灯有其一变化的最近的那一刻。在计算最短路的过程中,也可以适当用一些剪枝以减少计算量,比如如果d[u]+t[i]>=d[v],即就算现在立刻可以上路也不能更新d[v],那么自然就不用计算两个灯在什么候会变成相同颜色了,同时如果枚举过程中当前时刻已经超过了d[v]-t[i],那么也可以终止枚举了。

    #include<stdio.h>
    #include<string.h>
    #define MAXD 310
    #define MAXM 30000
    #define INF 0x5f5f5f5f5f5f5f5fll
    int N, M, S, T, e, first[MAXD], next[MAXM], v[MAXM], w[MAXM], icol[MAXD], it[MAXD], t[MAXD][2];
    int q[MAXD], inq[MAXD], p[MAXD];
    long long int d[MAXD];
    int gcd(int a, int b)
    {
    return b == 0 ? a : gcd(b, a % b);
    }
    void add(int a, int b, int c)
    {
    w[e] = c;
    v[e] = b;
    next[e] = first[a];
    first[a] = e;
    e ++;
    }
    void init()
    {
    int i, j, k, a, b, c;
    char st[5];
    scanf("%d%d", &N, &M);
    for(i = 1; i <= N; i ++)
    {
    scanf("%s%d%d%d", st, &a, &b, &c);
    it[i] = a;
    if(st[0] == 'B')
    {
    icol[i] = 0;
    t[i][0] = c, t[i][1] = b;
    }
    else
    {
    icol[i] = 1;
    t[i][0] = b, t[i][1] = c;
    }
    }
    memset(first, -1, sizeof(first));
    e = 0;
    for(i = 0; i < M; i ++)
    {
    scanf("%d%d%d", &a, &b, &c);
    add(a, b, c);
    add(b, a, c);
    }
    }
    long long int nextt(int a, int b, long long int now, long long int limit)
    {
    int sta, stb;
    long long int i, k;
    k = gcd(t[a][0] + t[a][1], t[b][0] + t[b][1]);
    k = (t[a][0] + t[a][1]) / k * (t[b][0] + t[b][1]);
    if(now + k < limit)
    limit = now + k;
    for(i = now; i < limit; i ++)
    {
    if(i < it[a])
    sta = icol[a];
    else
    {
    k = (i - it[a]) % (t[a][0] + t[a][1]);
    if(k < t[a][0])
    sta = (icol[a] ^ 1);
    else
    sta = icol[a];
    }
    if(i < it[b])
    stb = icol[b];
    else
    {
    k = (i - it[b]) % (t[b][0] + t[b][1]);
    if(k < t[b][0])
    stb = (icol[b] ^ 1);
    else
    stb = icol[b];
    }
    if(sta == stb)
    return i;
    }
    return -1;
    }
    void printpath(int cur)
    {
    if(cur == S)
    printf("%d", S);
    else
    {
    printpath(p[cur]);
    printf(" %d", cur);
    }
    }
    void solve()
    {
    int i, j, front, rear, u;
    long long int k;
    memset(d, 0x5f, sizeof(d));
    d[S] = 0;
    memset(inq, 0, sizeof(inq));
    front = rear = 0;
    q[rear ++] = S;
    while(front != rear)
    {
    u = q[front ++];
    if(front > N)
    front = 0;
    inq[u] = 0;
    for(i = first[u]; i != -1; i = next[i])
    if(d[u] + w[i] < d[v[i]])
    {
    k = nextt(u, v[i], d[u], d[v[i]] - w[i]);
    if(k != -1)
    {
    d[v[i]] = k + w[i];
    p[v[i]] = u;
    if(!inq[v[i]])
    {
    q[rear ++] = v[i];
    if(rear > N)
    rear = 0;
    inq[v[i]] = 1;
    }
    }
    }
    }
    if(d[T] == INF)
    printf("0\n");
    else
    {
    printf("%lld\n", d[T]);
    printpath(T);
    printf("\n");
    }
    }
    int main()
    {
    while(scanf("%d%d", &S, &T) == 2)
    {
    init();
    solve();
    }
    return 0;
    }


  • 相关阅读:
    python+selenium 定位隐藏元素
    数据库的几种去重方法总结
    用例设计方法与测试实践相结合思路
    边界值分析法
    等价类分析法
    CYQ.Data 支持分布式数据库(主从备)高可用及负载调试
    linux下rpm包安装、配置和卸载mysq
    linux命令 rpm
    Linux命令之rpm
    Linux rpm命令详解
  • 原文地址:https://www.cnblogs.com/staginner/p/2282766.html
Copyright © 2020-2023  润新知