sgu 103 Traffic Lights

    这道题难得不是算法,而是处理。

    题意就是让你求最短路,只有当两个点在某一秒颜色相同时,这条边才可以通行,输入首先给你 起点和终点, 然后给你 点数和边数, 接下来 n 行 初始颜色,初始颜色持续时间,蓝色持续时间,紫色持续时间。 再接下来m行,无向边的起点和终点以及通过所需的时间。

    题意他说的有些模糊,样例我看了很多遍也不对,后来才发现如果你在某一秒到达一个点,这一秒颜色和下一个点相同,但是下一秒这个点就要变色,那么是不能在这一秒走的,这个具体处理起来很麻烦

这篇博客说的很详细,戳链接:http://www.cnblogs.com/Rinyo/archive/2012/11/29/2795030.html

上代码……

#include <cstdio>

#include <cstring>

#include <iostream>

#include <cstdlib>

#include <algorithm>

#include <cmath>

#include <queue>

#define N 350

#define M 15000*2

#define inf 1<<30

using namespace std;



int n, m, S, T;

int p[N] = {0}, next[M], v[M], bnum = 0, c[M], fa[N];

int dis[N], vis[N], firstcolor[N], firstremain[N], remain[N][2];



void addbian(int x, int y, int z)

{

    bnum++; next[bnum] = p[x]; p[x] = bnum;

    v[bnum] = y; c[bnum] = z;

    bnum++; next[bnum] = p[y]; p[y] = bnum;

    v[bnum] = x; c[bnum] = z;

}



void calt(int now, int nowtime, int &color, int &changetime)

{

    if (nowtime < firstremain[now])

    {

        color = firstcolor[now];

        changetime = firstremain[now];

        return;

    }

    int k;

    k = (nowtime-firstremain[now]) % (remain[now][0]+remain[now][1]);

    nowtime -= k;

    if (firstcolor[now])

    {

        if (k < remain[now][0]) { color = 0; changetime = nowtime + remain[now][0]; }

        else { color = 1; changetime = nowtime + remain[now][1] + remain[now][0]; }

    }

    else

    {

        if (k < remain[now][1]) { color = 1; changetime = nowtime + remain[now][1]; }

        else { color = 0; changetime = nowtime + remain[now][0] + remain[now][1]; }

    }

}



int gettime(int x, int y, int nowtime, int dis, int f)

{

    int ca, cb, ta, tb, ta1, ca1;

    calt(x, nowtime, ca, ta);

    calt(y, nowtime, cb, tb);

    if (ca == cb) return nowtime + dis;

    if (ta == tb)

    {

        if (f == 0) return gettime(x, y, ta, dis, f+1);

        else if (nowtime <= firstremain[x] || nowtime <= firstremain[y])

            gettime(x, y, ta, dis, f+1);

        else return inf;

    }

    return min(ta, tb) + dis;

}



void spfa()

{

    queue<int> q;

    for (int i = 1; i <= n; ++i) { vis[i] = 0; dis[i] = inf; }

    q.push(S); dis[S] = 0; vis[S] = 1;

    while (!q.empty())

    {

        int now = q.front(); q.pop();

        int k = p[now];

        while (k != 0)

        {

            int t = gettime(now, v[k], dis[now], c[k], 0);

            if (dis[v[k]] > t)

            {

                dis[v[k]] = t; fa[v[k]] = now;

                if (!vis[v[k]])

                {

                    vis[v[k]] = 1;

                    q.push(v[k]);

                }

            }

            k = next[k];

        }

        vis[now] = 0;

    }

}



void print(int now)

{

    if (now == S) printf("%d ", S);

    else

    {

        print(fa[now]);

        if (now != T) printf("%d ", now);

        else printf("%d\n", T);

    }

}



int main()

{

    scanf("%d%d", &S, &T);

    scanf("%d%d", &n, &m);

    for (int i = 1; i <= n; ++i)

    {

        char s[2];

        scanf("%s", s);

        if (s[0] == 'B') firstcolor[i] = 0;

        else firstcolor[i] = 1;

        scanf("%d%d%d", &firstremain[i], &remain[i][0], &remain[i][1]);

    }

    for (int i = 1; i <= m; ++i)

    {

        int x, y, z; scanf("%d%d%d", &x, &y, &z);

        addbian(x, y, z);

    }

    spfa();

    if (dis[T] == inf)

    {

        printf("0\n");

        return 0;

    }

    printf("%d\n", dis[T]);

    print(T);

}

 

你可能感兴趣的:(tr)