题目描述

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

输入格式

第一行读入两个整数n,m,表示共n个点m条边。

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

输出格式

输出仅包括一行,记为所求路径的边权之积,由于答案可能很大,因此输出它模9987的余数即可。

样例数据 1

输入  [复制]

 

3 3 
1 2 3 
2 3 3 
1 3 10

输出

9

备注

对于20%的数据,n<=10。

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

这题把最短路的dist改成乘起来的形式,然后还要取模,看起来裸的最短路会爆

实际上对边权取个log之后,dist就变成相加了

这样没法保证路径上取模的正确性,所以要先搞出最短路的路径然后再算出ans

我只能说这题卡spfa卡的不错……死都是90

就是不写dij你咬我啊

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<queue>
#include<deque>
#include<set>
#include<map>
#include<ctime>
#define LL long long
#define inf 2147483647
#define pa pair<int,int>
#define pi 3.1415926535897932384626433832795028841971
#define md 100007
#define mod 9987
using namespace std;
struct edge{
int from,to,next,v;
double fv;
}e[800010],us[800010];
struct hashing{
int fr,to,next,rnk;
}hash[1000000];
int he[md];
int head[10010];
int n,m,cnt,cnt2,t,w,ans;
int q[100010];
double dist[100010];
int fa[100010];
int fav[100010];
bool mrk[100010];
inline int searc(int fr,int to)
{
int now=((fr+213)*(to+250))%md;
for (int i=he[now];i;i=hash[i].next)
if (hash[i].fr==fr&&hash[i].to==to)return hash[i].rnk;
return -1;
}
inline void ins_ha(int fr,int to,int rnk)
{
int now=((fr+213)*(to+250))%md;
hash[++cnt2].fr=fr;
hash[cnt2].to=to;
hash[cnt2].rnk=rnk;
hash[cnt2].next=he[now];
he[now]=cnt;
}
inline void ins_ed(int u,int v,int w)
{
us[++cnt].to=v;
us[cnt].from=u;
us[cnt].v=w;
us[cnt].next=head[u];
head[u]=cnt;
}
inline void ins_e(int u,int v,int w)
{
e[++cnt].to=v;
e[cnt].from=u;
e[cnt].v=w;
e[cnt].next=head[u];
head[u]=cnt;
}
inline LL read()
{
LL x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
inline void spfa(int S)
{
for (int i=1;i<=n;i++)mrk[i]=0;
for (int i=1;i<=n;i++)dist[i]=inf;
memset(q,0,sizeof(q));
q[0]=S;mrk[S]=1;dist[S]=0;
t=0;w=0;
do
{
int now=q[t];
t=(t+1)%md;
for (int i=head[now];i;i=e[i].next)
if (dist[e[i].to]>dist[now]+e[i].fv)
{
dist[e[i].to]=dist[now]+e[i].fv;
fa[e[i].to]=now;
fav[e[i].to]=e[i].v;
if (!mrk[e[i].to])
{
mrk[e[i].to]=1;
if (dist[q[t]]>dist[e[i].to])
{
t=(t-1+md)%md;
q[t]=e[i].to;
}
else
{
w=(w+1)%md;
q[w]=e[i].to;
}
}
}
mrk[now]=0;
}
while (t!=w);
}
int main()
{
n=read();m=read();
for (int i=1;i<=m;i++)
{
int x=read(),y=read(),z=read();
int fnd=searc(x,y);
if (fnd==-1)
{
ins_ed(x,y,z);
ins_ha(x,y,cnt);
}else
{
us[fnd].v=min(us[fnd].v,z);
}
}
memset(head,0,sizeof(head));
int sum=cnt;cnt=0;
for (int i=1;i<=sum;i++)
{
ins_e(us[i].from,us[i].to,us[i].v);
}
for (int i=1;i<=cnt;i++)
e[i].fv=log(e[i].v);
spfa(1);
int s=n,ans=1;
while (s!=1)
{
ans=(ans*fav[s])%mod;
s=fa[s];
}
printf("%d\n",ans);
}

  

codecomb 2090【最小乘积路】的更多相关文章

  1. C语言 · 最小乘积(基本型)

    问题描述 给两组数,各n个. 请调整每组数的排列顺序,使得两组数据相同下标元素对应相乘,然后相加的和最小.要求程序输出这个最小值. 例如两组数分别为:1 3 -5和-2 4 1 那么对应乘积取和的最小 ...

  2. 最小瓶颈路 Uva 534 Frogger

    说明:关于Uva的题目,可以在vjudge上做的,不用到Uva(那个极其慢的)网站去做. 最小瓶颈路:找u到v的一条路径满足最大边权值尽量小 先求最小生成树,然后u到v的路径在树上是唯一的,答案就是这 ...

  3. UVALive 5713 Qin Shi Huang's National Road System秦始皇修路(MST,最小瓶颈路)

    题意: 秦始皇要在n个城市之间修路,而徐福声可以用法术位秦始皇免费修1条路,每个城市还有人口数,现要求徐福声所修之路的两城市的人口数之和A尽量大,而使n个城市互通需要修的路长B尽量短,从而使得A/B最 ...

  4. bzoj2395[Balkan 2011]Timeismoney最小乘积生成树

    所谓最小乘积生成树,即对于一个无向连通图的每一条边均有两个权值xi,yi,在图中找一颗生成树,使得Σxi*Σyi取最小值. 直接处理问题较为棘手,但每条边的权值可以描述为一个二元组(xi,yi),这也 ...

  5. UVA 11354 Bond(最小瓶颈路+倍增)

    题意:问图上任意两点(u,v)之间的路径上,所经过的最大边权最小为多少? 求最小瓶颈路,既是求最小生成树.因为要处理多组询问,所以需要用倍增加速. 先处理出最小生成树,prim的时间复杂度为O(n*n ...

  6. HDU5697 刷题计划 dp+最小乘积生成树

    分析:就是不断递归寻找靠近边界的最优解 学习博客(必须先看这个): 1:http://www.cnblogs.com/autsky-jadek/p/3959446.html 2:http://blog ...

  7. bzoj3571: [Hnoi2014]画框 最小乘积匹配+最小乘积XX总结,

    思路大概同bzoj2395(传送门:http://www.cnblogs.com/DUXT/p/5739864.html),还是将每一种匹配方案的Σai看成x,Σbi看成y,然后将每种方案转化为平面上 ...

  8. bzoj3571————2016——3——12(最小乘积匹配)

    bzoj3571 传送门http://www.lydsy.com/JudgeOnline/problem.php?id=3571 题解: ——————来自伟大的thy大神  http://blog.c ...

  9. 【UVA534】Frogger 最小瓶颈路

    题目大意:给定一张 N 个点的完全图,求 1,2 号节点之间的一条最小瓶颈路. 题解:可知,最小瓶颈路一定存在于最小生成树(最小瓶颈树)中.因此,直接跑克鲁斯卡尔算法,当 1,2 号节点在同一个联通块 ...

随机推荐

  1. 将DataTable转化为json对象

    private string DataTableTojson(DataTable dt)         {              List> list=new List>();    ...

  2. 链表的基本操作(Basic Operations on a Linked List)

    链表可以进行如下操作: 创建新链表 增加新元素 遍历链表 打印链表 下面定义了对应以上操作的基本函数. 创建新链表 新链表创建之后里面并没有任何元素,我们要为数据在内存中分配节点,再将节点插入链表.由 ...

  3. 在eclipse中使用svn

    作为一名程序员,svn是比较常用也必然会使用到的一个工具,它的全拼为Subversion,是一个开源的版本控制系统,可以对每次修改的文件和目录进行准确记录,以便在使用的时候及时提取.本文主要介绍如何在 ...

  4. 格而知之16:我所理解的Block(2)

    11.那么Block到底是怎么实现的呢?试一试通过将Block 的代码转换成普通C语言代码来查看它的实现过程. 要将OC代码转换成C语言代码,可以使用clang编译的一个命令: 通过这个命令能把指定文 ...

  5. Bom和Dom编程以及js中prototype的详解

    一.Bom编程: 1.事件练习: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "h ...

  6. OSX: 私人定制Dock默认程序图标

    不论什么一个新用户第一次登陆后,OSX都会自己主动地在用户的Dock中列出系统默认的应用程序图标,这些图标随着OSX版本号的不同而不同. 系统管理员有的时候须要改变这些系统默认图标,或者加入自己的或者 ...

  7. 带CheckBox的TreeView网上出错问题解决办法

    问题描述:TreeView上传到服务器,预览效果发现节点图片不显示.展开合并功能缺失.解决办法: 以下是我个人的解决办法,最终的效果实现了,但是还有一点点小遗憾,就是页面上有基于微软的调用js的报错信 ...

  8. break,continue,return 区别

    using System;using System.Collections.Generic;using System.Text; namespace breakcontinue_test{    cl ...

  9. 1215.1——动态分配内存的补充realloc

    当再次在原来申请的内存基础上再加内存的时候用realloc,如果第一次分配的内存后面存储地方够用,则连着原来的申请,如果不够用,就重新找到一块够用的地方,然后把原来的复制过去 int main(int ...

  10. 我跟着siki学Unity3D游戏开发——PongGame

    一.屏幕坐标转换为世界坐标. 1.游戏逻辑,根据界面布局,将墙体控制到对应的位置: vector3 position=Camer.main.ScreenToWorldPoint(new vetor2( ...