现在的位置: 首页 > 综合 > 正文

codecomb 2090【最小乘积路】

2018年01月12日 ⁄ 综合 ⁄ 共 2463字 ⁄ 字号 评论关闭

题目描述

给定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);
}

抱歉!评论已关闭.