最短路

【题目描述】

现给定一张N(N <= 1000)个节点的带权有向图,求从1到N的路径中边权之积最小的简单路径。

【输入描述】

第一行输入两个整数N、M(M <= 1000000),表示节点数目及边数目;

接下来M行,每行输入三个正整数X、Y、Z,表示节点X到节点Y存在一条边权为Z(Z <= 10000)的边。

【输出描述】

输出一个数,表示答案 mod 9987的值。

【输入样例】

3 3

1 2 3

2 3 3

1 3 10

【输出样例】

9

Dijkstra:

源代码:

#include<cstdio>
#include<cmath>
#include<queue>
#include<vector>
#define INF 9987
using namespace std;
struct Node
{
    int To;
    double W;
    bool operator < (const Node &t) const
    {
        if (W==t.W)
          return To<t.To;
        else
          return W>t.W;
    }
};
priority_queue <Node> Q;
vector <Node> List[1001];
int n,m,Ans=1,f[1001],Map[1001][1001];
double i[1001];
void Dijkstra() //Dijkstra+优先队列。
{
    i[1]=0;
    Node t;
    t.To=1;
    t.W=0;
    Q.push(t);
    while (!Q.empty())
    {
        t=Q.top();
        Q.pop();
        for (int a=0;a<List[t.To].size();a++)
        {
            Node T=List[t.To][a];
            if (i[T.To]>t.W+T.W)
            {
                i[T.To]=t.W+T.W;
                T.W=i[T.To];
                Q.push(T);
                f[T.To]=t.To;
            }
        }
    }
}
int main()
{
    scanf("%d%d",&n,&m);
    for (int a=1;a<=n;a++) //double总是不能memset()赋值。
      i[a]=1000000000;
    for (int a=0;a<m;a++)
    {
        Node t;
        int T,S;
        scanf("%d%d%d",&T,&t.To,&S);
        t.W=log(S);
        List[T].push_back(t);
        Map[T][t.To]=S;
    }
    Dijkstra();
    for (int a=n;f[a];a=f[a])
      Ans=Ans*(Map[f[a]][a]%INF)%INF;
    printf("%d",Ans);
    return 0;
}

SPFA:

源代码:

#include<cstdio>
#include<cmath>
#include<cstring>
#include<queue>
#include<vector>
#define INF 9987
using namespace std;
struct Node
{
    int S,To;
    double W;
};
deque <int> Q;
vector <Node> List[1001];
int n,m,Ans=1,f[1001];
bool In[1001];
double i[1001];
void SPFA() //SPFA+SLF。
{
    i[1]=0;
    In[1]=true;
    Q.push_back(1);
    while (!Q.empty())
    {
        int t=Q.front();
        Q.pop_front();
        In[t]=false;
        for (int a=0;a<List[t].size();a++)
        {
            Node T=List[t][a];
            if (i[T.To]>i[t]+T.W)
            {
                i[T.To]=i[t]+T.W;
                f[T.To]=t;
                if (!In[T.To])
                {
                    In[T.To]=true;
                    if (!Q.empty()&&i[T.To]<i[Q.front()])
                      Q.push_front(T.To);
                    else
                      Q.push_back(T.To);
                }
            }
        }
    }
}
int Find(int t1,int t2)
{
    for (int a=0;a<List[t1].size();a++)
      if (List[t1][a].To==t2)
        return List[t1][a].S;
}
int main()
{
    scanf("%d%d",&n,&m);
    for (int a=1;a<=n;a++)
      i[a]=1000000000;
    for (int a=0;a<m;a++)
    {
        int T;
        Node t;
        scanf("%d%d%d",&T,&t.To,&t.S);
        t.W=log(t.S); //数论的结合体,好题。
        List[T].push_back(t);
    }
    SPFA();
    for (int a=n;f[a];a=f[a]) //DFS查找,注意结束条件。
      Ans=Ans*(Find(f[a],a)%INF)%INF;
    printf("%d",Ans);
    return 0;
}

/*
    利用log(N)+log(M)=log(N*M),即可转化为最短路问题。
*/
原文地址:https://www.cnblogs.com/Ackermann/p/6023693.html