• 【题解】 P2384 最短路(边权之积最短路)


    P2384 最短路(边权之积最短路)

    题目背景

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

    题目描述

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

    输入格式

    第一行读入两个整数 nn,mm,表示共 nn 个点 mm 条边。 接下来 mm 行,每行三个正整数 xx,yy,zz,表示点 xx到点 yy 有一条边权为z的边。

    输出格式

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

    废话当然是一个数了w

    //谢fyszzhouzj指正w

    输入输出样例

    输入 #1

    3 3
    1 2 3 
    2 3 3 
    1 3 10
    

    输出 #1

    9
    

    说明/提示

    对于 20%20% 的数据,nleq 10n≤10。

    对于 100%100% 的数据,nleq 10^3n≤103,mleq 10^6m≤106。边权不超过 10^4104。

    发现乘法和加法一样是可以用迪杰斯特拉的贪心来实现乘法最短路的。

    但是这样乘起来会爆ll,无法储存,所以对乘法的结果进行hash,dis存储边权乘积取log后的结果。

    不带负环的最短路一定是简单路径,即每个节点最多只经过一遍。在松弛操作的时候,pre[终点v] = pre[起点u]表示v是由u过来的,preed[v] = 边的编号e,从而存储下来边权。最后我们遍历最短路,求出答案即可。

    由于是存对数,所以dis要double。

    在取余的过程中,ans可能模9987后等于0,此时我们要让ans=1,然后接着乘。

    真正ans=0的是n=1只有1个点的,此时ans=0。

    #include<queue>
    #include<cstdio>
    #include<string>
    #include<cstdlib>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define ll long long
    #define inf 0x3fffffff
    #define mod 9987
    using namespace std;
    const int maxn = 1010;
    const int maxm = 2000010; 
    struct Edge{
    	int to, nxt, k;
    }ed[maxm];
    int first[maxn], en, n, m, k, u, v;
    void add(int u, int v, int k){
    	ed[++en].to = v;
    	ed[en].nxt = first[u];
    	ed[en].k = k;
    	first[u] = en;
    }
    bool vst[maxn];
    double dis[maxn];
    priority_queue<pair<int, int> > q;
    
    int pre[maxn], preed[maxn]; 
    void dijkstra(int s){
    //	memset(dis, 0x3f, sizeof dis);
    	for(int i = 1; i <= n; i++)	dis[i] = 1061169567;
    	memset(vst, 0, sizeof(vst));
    	dis[s] = 0;
    //	vst[s] = 1;
    	q.push({0, s});
    	while(q.size()){
    		int u = q.top().second;
    		q.pop();
    		if(vst[u])	continue;
    		vst[u] = 1;
    		for(int e = first[u]; e; e = ed[e].nxt){
    			int v = ed[e].to, k = ed[e].k;
    			if(dis[v] > dis[u] + log(k)){
    				dis[v] = dis[u] + log(k);
    				preed[v] = e;
    				pre[v] = u;
    				if(!vst[v]){
    //					vst[v] = 1;
    					q.push({-dis[v], v} );
    				}
    			}
    		} 
    	}
    }
    ll ans = 1;
    int main(){
    	cin >> n >> m;
    	for(int i = 1; i <= m; i++){
    		scanf("%d%d%d", &u, &v, &k);
    		add(u, v, k);
    	} 
    	if(n == 1){
    		cout << 0 << endl;
    		return 0;
    	}
    	dijkstra(1);
    //	for(int i = 1; i <= n; i++)	cout << dis[i] << " ";
    //	cout << endl; 
    	int pos = n;
    	while(pos > 1){
    //		cout << ed[preed[pos]].to << endl;
    		ans *= ed[preed[pos]].k;
    		ans %= mod;
    		pos = pre[pos];
    //		cout << ans << endl;
    		if(ans == 0)	ans = 1;
    	}
    	cout << ans << endl;
    	return 0;
    }
    
  • 相关阅读:
    导入Excel的时候使用TransactionScope事务控制来进行数据
    【项目相关】MVC中将WebUploader进行封装
    【项目相关】MVC中使用WebUploader进行图片预览上传以及编辑
    Java学习-2 其它公司合作项目源码分析
    Linux开发环境搭建
    新春畅想未来
    Java学习-1 框架、测试及学习误区
    Java学习-1 Myeclipse与Idea
    又到了一年一度圣诞新年立志许愿的时候了
    WebStorm神器啊,一旦上手根本停不下来
  • 原文地址:https://www.cnblogs.com/ZhengkunJia/p/13577149.html
Copyright © 2020-2023  润新知