码迷,mamicode.com
首页 > 其他好文 > 详细

P2384 最短路 最短路

时间:2019-08-09 20:02:57      阅读:107      评论:0      收藏:0      [点我收藏+]

标签:getc   mes   如何   最小   name   乘法   space   转化   const   

题目背景

狗哥做烂了最短路,突然机智的考了Bosh一道,没想到把Bosh考住了...你能帮Bosh解决吗?

他会给你\(100000000000000000000000000000000000\)%\(10\)金币w

题目描述

给定n个点的带权有向图,求从1到n的路径中边权之积最小的简单路径。

输入格式

第一行读入两个整数n,m,表示共n个点m条边。 接下来m行,每行三个正整数x,y,z,表示点x到点y有一条边权为z的边。

输出格式

输出仅包括一行,记为所求路径的边权之积,由于答案可能很大,因此狗哥仁慈地让你输出它模\(9987\)的余数即可。

废话当然是一个数了w

//谢fyszzhouzj指正w

对于20%的数据,\(n<=10\)

对于100%的数据,\(n<=1000,m<=1000000\)。边权不超过\(10000\)

输入输出样例

输入 #1

3 3
1 2 3 
2 3 3 
1 3 10

输出 #1

9

说明/提示

好好看一看再写哟w

题解

考虑如何将问题进行转化, 题意是要使乘积最大, 而最短路只能处理加和最大。

取Log运算,因为Log单调递增, 且乘法运算可以转化为Log的加法运算。

因此, 对路径上的边权进行取Log运算并跑最短路。

pre[i]记录点 i 的前驱, p_val[i]记录点 i 与前驱所连边的权值。

记录答案即可。

code:

#include <iostream>
#include <cstdio>
#include <queue>
#include <cmath>
using namespace std;
const int N = 1e3 + 5, M = 1e6 + 5, mod = 9987;
int read() {
    int x = 0, f = 1; char ch = getchar();
    while(! isdigit(ch)) f = (ch=='-')?-1:1, ch = getchar();
    while(isdigit(ch)) x = (x<<3)+(x<<1)+(ch^48), ch = getchar();
    return x * f;
}
int n, m, ans, cnt, head[N], vis[N], pre[N], p_val[N];
struct edge { int to, nxt, val; } e[M];
double dis[N];
void add(int from, int to, int val) {
    e[++ cnt].to = to;
    e[cnt].val = val;
    e[cnt].nxt = head[from];
    head[from] = cnt;
}
void spfa(int s) {
    queue <int> q; q.push(s);
    for(int i = 1;i <= n;i ++) dis[i] = 1e9 + 7;
    dis[s] = 0; vis[s] = 1;
    while(! q.empty()) {
        int tp = q.front(); q.pop();
        vis[tp] = 0;
        for(int i = head[tp]; i ;i = e[i].nxt) {
            int to = e[i].to;
            if(vis[to]) continue;
            double dist = log(e[i].val);
            if(dis[to] > dis[tp] + dist) {
                dis[to] = dis[tp] + dist;
                pre[to] = tp; p_val[to] = e[i].val;
                if(! vis[to]) q.push(to), vis[to] = 1;
            }
        }
    }
    ans = 1;
    int t = n;
    while(t != 1) {
        (ans *= p_val[t]) %= mod;
        t = pre[t];
    }
}
int main() {
    n = read(); m = read();
    for(int i = 1, x, y, z;i <= m;i ++) {
        x = read(); y = read(); z = read();
        add(x, y, z); add(y, x, z);
    }
    spfa(1);
    printf("%d\n", ans);
    return 0;
}

P2384 最短路 最短路

标签:getc   mes   如何   最小   name   乘法   space   转化   const   

原文地址:https://www.cnblogs.com/Paranoid-LS/p/11329039.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!