P2384 最短路 最短路

题目背景

狗哥做烂了最短路,突然机智的考了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;
}

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

时间: 2024-10-31 11:52:32

P2384 最短路 最短路的相关文章

poj 3463 Sightseeing(最短路+次短路)

http://poj.org/problem?id=3463 大致题意:给出一个有向图,从起点到终点求出最短路和次短路的条数之和. 解法: 用到的数组:dis[i][0]:i到起点的最短路,dis[i][1]:i到起点的严格次短路 vis[i][0],vis[i][1]:同一维的vis数组,标记距离是否已确定 sum[i][0]:i到起点的最短路条数,sum[i][1]:i到起点的次短路条数 同一维dijkstra,内循环先找出最短的距离(次短路或最短路)d,然后枚举与该点相连的点: if(d

nyoj1006(最短路次短路spfa)

偷西瓜 时间限制:1000 ms  |  内存限制:65535 KB 难度:4 描述 对于农村的孩子来说最大的乐趣,莫过于和小伙伴们一块下地偷西瓜了,虽然孩子们条件不是很好,但是往往他们很聪明,他们总在计算着到达瓜田的距离,以及逃跑的路线,他们总是以最短的距离冲到瓜田里面,然后以最短的距离回到出发的地方,不过瓜田的大人们已经在他们来的路上等待他们.于是聪明的小伙伴们便不走过的路,即每条路只走一遍,如果小伙伴们回不到出发的地方,他们就说"eating", 我们假设 有 n (n<=

HDU 2544 最短路 (最短路)

最短路 Time Limit: 5000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 31955    Accepted Submission(s): 13845 Problem Description 在每年的校赛里,所有进入决赛的同学都会获得一件很漂亮的t-shirt.但是每当我们的工作人员把上百件的衣服从商店运回到赛场的时候,却是非常累的!所以现在他们想要寻找最

HDU ACM 2544 最短路-&gt;最短路

最短路,简单题,floyd实现,在求最短路时一定要是是最大节点编号maxnum而不是输入的n,否则是错的. #include<iostream> using namespace std; int map[105][105]; //无向图 void Init() { int MAX=1000000,i,j; for(i=1;i<=104;i++) for(j=1;j<=104;j++) if(i==j) map[i][j]=0; else map[i][j]=MAX; } void

HDU 6181 次短路(K短路)

Two Paths Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 153428/153428 K (Java/Others)Total Submission(s): 613    Accepted Submission(s): 312 Problem Description You are given a undirected graph with n nodes (numbered from 1 to n) and m edge

poj 3463 最短路+次短路

独立写查错不能,就是维护一个次短路的dist 题意:给定一个有向图,问从起点到终点,最短路+比最短路距离长1的路的个数. Sample Input25 81 2 31 3 21 4 52 3 12 5 33 4 23 5 44 5 31 55 62 3 13 2 13 1 104 5 25 2 75 2 74 1 Sample Output32 2015-05-14 1 #include<cstdio> 2 #include<iostream> 3 #include<algo

hdu 2544最短路——最短路的初次总结

这是一道标准的模板题,所以拿来作为这一段时间学习最短路的总结题目. 题意很简单: 有多组输入数据,每组的第一行为两个整数n, m.表示共有n个节点,m条边. 接下来有m行,每行三个整数a, b, c.表示从a到b或从b到a长度为c. 求从1到n的最短路. 先说Floyd—— 这个算法看上去就是一个三重for循环,然后在循环里不断对选择的两个节点进行松弛(感觉松弛这两个字很高端有没有). 算法时间复杂度为O(n^3),n为节点数.所以一般可以用来处理规模1000以下的数据(即100数量级的,但是如

逻辑运算符短路与,短路或

1.逻辑运算符说明 a:逻辑运算符一般用于连接boolean类型的表达式或者值. b:表达式:就是用运算符把常量或者变量连接起来的符合java语法的式子. 2.&&和&(遇false则false)的区别? a:最终结果一样. b:&&具有短路效果(可以提高一点效率).左边是false,右边不执行. &是无论左边是false还是true,右边都会执行 3.同理||和|(遇true则true)的区别?(学生自学) a:最终结果一样. b:||具有短路效果(可以提

BZOJ 1726: [Usaco2006 Nov]Roadblocks第二短路( 最短路 )

从起点和终点各跑一次最短路 , 然后枚举每一条边 , 更新answer ----------------------------------------------------------------------------------------------------- #include<cstdio> #include<cstring> #include<algorithm> #include<iostream> #include<queue&g