NC 22600 Dijkstra

题意

传送门 NC 22600

题解

观察到 f ( x ) f(x) f(x) 的值具有周期性且周期为 3 3 3

f ( x ) = 1 1 − x f(x)=\frac{1}{1-x} f(x)=1x1

f ′ ( x ) = 1 1 − f ( x ) = x − 1 x f'(x)=\frac{1}{1-f(x)}=\frac{x-1}{x} f(x)=1f(x)1=xx1

f ′ ′ ( x ) = 1 1 − f ′ ( x ) = x f''(x)=\frac{1}{1-f'(x)}=x f(x)=1f(x)1=x

那么对于图上每一个点,都对应 3 3 3 种状态(对应下一条边的 3 3 3 种边权值), D i j k s t r a Dijkstra Dijkstra 求解最短路,取终点 3 3 3 个状态的最小值即可。

#include 
using namespace std;
#define inf 0x3f3f3f3f
#define maxv 100005
struct node
{
    double d;
    int v, n;
    bool operator<(const node &a) const
    {
        return d > a.d;
    }
};
struct edge
{
    int to;
    double cost[3];
    edge() {}
    edge(int to, double *c) : to(to)
    {
        for (int i = 0; i < 3; i++) cost[i] = c[i];
    }
};
vector<edge> G[maxv];
int n, m, used[maxv][3];
double d[maxv][3];

void dijkstra(int s)
{
    priority_queue<node> que;
    for (int i = 1; i <= n; i++) fill(d[i], d[i] + 3, inf);
    memset(used, 0, sizeof(used));
    d[s][0] = 0;
    que.push(node{0, s, 0});
    while (!que.empty())
    {
        node p = que.top();
        que.pop();
        int v = p.v, n = p.n;
        if (used[v][n]) continue;
        used[v][n] = 1;
        for (int i = 0; i < G[v].size(); i++)
        {
            edge &e = G[v][i];
            double d2 = abs(e.cost[n]) + d[v][n];
            int n2 = (n + 1) % 3;
            if (d2 < d[e.to][n2])
            {
                d[e.to][n2] = d2;
                que.push(node{d[e.to][n2], e.to, n2});
            }
        }
    }
}

int main()
{
    scanf("%d%d", &n, &m);
    for (int i = 0; i < m; i++)
    {
        int u, v, w;
        scanf("%d%d%d", &u, &v, &w);
        double c[3];
        c[0] = w, c[1] = 1 / (1 - c[0]), c[2] = 1 / (1 - c[1]);
        G[u].push_back(edge{v, c});
        G[v].push_back(edge{u, c});
    }
    dijkstra(1);
    double res = *min_element(d[n], d[n] + 3);
    if (res == inf) printf("-1\n");
    else printf("%.3f\n", res);
    return 0;
}

你可能感兴趣的:(图论)