Lightoj 1321 Sending Packets(Bellman-Ford)

题意

给定一个无向图,边的权值为小于1的小数,表示通过这条边的数据成功传输到另一边的可能性,0.8表示有百分之八十的可能性传输过去。问你从起点到终点,最大的传输成功率多大。

分析

根据题意,相当于求一个最长路,dijkstra有点难写,直接用bellman-ford,因为边权值都是小于1的,所以更新操作用的乘法永远是越来越小的,我们刚好要最大的。所以比较方便就能处理出来,然后得出最大的传输成功率以后结合题意中的其他要求进行简单的运算就能得出答案了。

代码

#define rep(x,y,z) for(int x=y;x<z;x++)
#define drep(x,y,z) for(int x=y;x>=z;x--)
#define pb(x) push_back(x)
#define mp(x,y) make_pair(x,y)
#define clr(x,y) memset(x,y,sizeof(x))
#define fi first
#define se second

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <vector>
#include <queue>
using namespace std;

const int N = 110;

vector<pair<pair<int,int>,double> > edge;
double val[N];
double dp[N][N];

void init(){
    edge.clear();
    clr(val,0);
    clr(dp,0);
}

void read(int m){
    rep(i,0,m){
        int u , v , w;
        scanf("%d %d %d",&u,&v,&w);
        edge.pb(mp(mp(u,v),double(w)/100.0));
        edge.pb(mp(mp(v,u),double(w)/100.0));
    }
}

double slove(int n){
    val[0] = 1;
    int size = edge.size();
    while(1){
        bool ok = 0;
        rep(i,0,size){
            int u = edge[i].fi.fi;
            int v = edge[i].fi.se;
            double w = edge[i].se;

            if(val[u] * w > val[v]){
                ok = 1;
                val[v] = val[u] * w;

            }
        }
        if(!ok) break;
    }
    return val[n - 1];
}

int main(){
    int t;
    scanf("%d",&t);
    rep(tt,1,t+1){
        int n , m , s , k;
        scanf("%d %d %d %d",&n,&m,&s,&k);
        init();
        read(m);
        double ans = slove(n);
        //
        ans = (k / ans) * 2 * s;
        //
        printf("Case %d: %lf
",tt,ans);
    }


    return 0;
}
原文地址:https://www.cnblogs.com/ticsmtc/p/6107225.html