• 最短路


    题目描述

    给你一个n个点,m条边的无向图,定义一条路径的化学系数为路径上所有边的积。
    请你找出一条1到n的路径,使它的化学系数最小,并输出这个化学系数对998244353取模
    后的结果。

    输入格式
    第一行两个正整数n,m
    接下来m行,每行3个正整数u,v,w,表示从u到v有一条边权为w的边

    输出格式
    一行一个整数ans表示最小的化学系数

    样例输入
    3 3
    1 2 3
    2 3 3
    1 3 10

     

    样例输出
    9

     

    别看这是边权之积,但是spfa,dijkstra照样能跑。不过因为会爆long long,因此期望得分50.

     

    正解:其实这是一道数学题……

    高一的我们都学过,loga + logb = log(a * b)。所以对于每一条边,先取一个log,然后跑一遍最短路,最后还原dis就可。

     

    小优化:为了避免精度问题,可以直接在计算的时候取log,并记录路径,最后反过来求边权之积。

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<algorithm>
     4 #include<cmath>
     5 #include<cstring>
     6 #include<vector>
     7 #include<queue>
     8 using namespace std;
     9 typedef long long ll;
    10 const int maxn = 2e3 + 5;
    11 const int INF = 0x3f3f3f3f;
    12 const int mod = 998244353;
    13 
    14 int n, m;
    15 vector<int> v[maxn], c[maxn];
    16 bool done[maxn];
    17 double dis[maxn];
    18 int path[maxn], len[maxn];
    19 void spfa(int s)
    20 {
    21     for(int i = 1; i <= n; ++i) dis[i] = INF;
    22     queue<int> q;
    23     q.push(s); dis[s] = 0;
    24     while(!q.empty())
    25     {
    26         int now = q.front(); q.pop(); done[now] = 0;
    27         for(int i = 0; i < (int)v[now].size(); ++i)
    28         {
    29             if(dis[now] + log(c[now][i]) < dis[v[now][i]])
    30             {
    31                 dis[v[now][i]] = dis[now] + log(c[now][i]);
    32                 path[v[now][i]] = now; len[v[now][i]] = c[now][i];
    33                 if(!done[v[now][i]])
    34                 {
    35                     q.push(v[now][i]); done[v[now][i]] = 1;
    36                 }
    37             }
    38         }
    39     }
    40     int x = n;
    41     ll ans = 1;
    42     while(path[x])
    43     {
    44         ans *= len[x]; ans %= mod;
    45         x = path[x];
    46     }
    47     printf("%lld
    ", ans);
    48 }
    49 
    50 int main()
    51 {
    52     scanf("%d%d", &n, &m);
    53     for(int i = 1; i <= m; ++i)
    54     {
    55         int a, b, cost; scanf("%d%d%d", &a, &b, &cost);
    56         v[a].push_back(b); c[a].push_back(cost);
    57         v[b].push_back(a); c[b].push_back(cost);
    58     }
    59     spfa(1);
    60     return 0;
    61 }
  • 相关阅读:
    傅里叶变换相关公式
    Java中的IO流
    oracle sqlplus 命令行中创建存储过程
    Redis 缓存数据库的使用场景
    Java 数值格式化类-NumberFormat
    Idea_类注释、属性注释、方法注释
    博客·HelloWorld
    【4】Django 创建第一个模块应用
    【3】Django创建第一个项目
    理解面向对象三大特征与魔法方法?
  • 原文地址:https://www.cnblogs.com/mrclr/p/8994898.html
Copyright © 2020-2023  润新知