HDU-4318 Power transmission 模型转化

这题在比赛的时候没做出来实在是不应该。本来也是用对数处理的,但是后面写的七零八落的。

这题也可以直接求,记录每个点最少消耗的流量,剩余流量为初始流量减去这个值,逐步向下迭代。

当然这里可以去求他的剩余值,根据公式 最后的流量 L = I * (1-p1) * (1-p2) * ... * (1-pn) 我们对两边同时取对数的话,那么我们就将乘法化成了加法,并且直接求一个最长路就可以了。最后再拿总流量减去最大的剩余量即可。

代码如下:

#include <cstdio>

#include <cstring>

#include <cstdlib>

#include <queue>

#include <algorithm>

#include <cmath>

#define eps 1e-6

using namespace std;



int head[50005], N, idx, S, T, P, q[10000005], visit[50005];

double dis[50005];



struct Edge

{

    int v, next;

    double fee;

}e[2500005];



void insert(int x, int y, int fee)

{

    ++idx;

    e[idx].v = y, e[idx].fee = log(1 - fee/100.);

    e[idx].next = head[x], head[x] = idx;

}



void spfa()

{

    int front = 0, tail = 1, pos;

    q[tail] = S;

    fill(dis+1, dis+N+1, 0);

    dis[S] = log(1.*P);

    while (front != tail) {

        pos = q[++front];

        visit[pos] = 0;

        for (int u = head[pos]; u != -1; u = e[u].next) {

            if (dis[pos] + e[u].fee - dis[e[u].v] > eps) {

                dis[e[u].v] = dis[pos] + e[u].fee;

                if (!visit[e[u].v]) {  // spfa中防止多次入队

                    q[++tail] = e[u].v;

                    visit[e[u].v] = 1;

                }

            }

        }

    }

    if (dis[T] == 0) {

        puts("IMPOSSIBLE!");

    }

    else {

        printf("%.2lf\n", P - exp(dis[T]));

    }

}



int main()

{  

    int M, y, fee;

    while (scanf("%d", &N) == 1) {

        memset(head, -1, sizeof (head));

        memset(visit, 0, sizeof (visit));

        idx = -1;

        for (int i = 1; i <= N; ++i) {

            scanf("%d", &M);

            for (int j = 1; j <= M; ++j) {

                scanf("%d %d", &y, &fee);

                insert(i, y, fee);

            }

        }

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

        spfa();

    }

    return 0;

}

你可能感兴趣的:(HDU)