zoukankan      html  css  js  c++  java
  • codecomb 2090【最小乘积路】

    题目描述

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

      

    ——by zhber,转载请注明来源
  • 相关阅读:
    linux同一客户端多个git账号的配置
    linux同一台机子上用多个git 账号
    执行ssh-add时出现Could not open a connection to your authentication agent
    国内常用NTP服务器地址及IP
    PHP双引号的隐患
    mysql 累加求和
    php实现Facebook风格的 time ago函数
    Mysql之数据库设计规范
    搭建Git服务器
    win7下如何根据端口号杀掉进程
  • 原文地址:https://www.cnblogs.com/zhber/p/4035881.html
Copyright © 2011-2022 走看看