热浪

【题目描述】

给定一张地图,包含T个城镇(1 <= T <= 2500)和M(1 <= M <= 6200)条直接连接两个城镇的道路,每条道路由起点S、终点E(1 <= S <= T,1 <= E <= T)以及花费C(1 <= C <= 1000)构成,求从起始城镇Start(1 <= Start <= T)到终点城镇End(1 <= End <= T)所能得到的最小总费用是多少。

【输入描述】

第一行输入四个整数T、M、Start、End;

接下来M行,每行输入三个整数S、E、C。

【输出描述】

输出一个整数,表示答案。

【输入样例】

7 11 5 4

2 4 2

1 4 3

7 2 2

3 4 3

5 7 5

7 3 3

6 1 1

6 3 4

2 4 3

5 6 3

7 2 1

【输出样例】

7

Dijkstra+优先队列优化:

源代码:

#include<cstdio>
#include<cstring>
#include<queue>
#include<vector>
using namespace std;
struct Node
{
    int To,S;
    Node(int t1,int t2) //似乎是强制类型转换。
    {
        To=t1;
        S=t2;
    }
    bool operator < (const Node &t) const //看来得背过了,重载运算符。
    {
        if (S==t.S)
          return To<t.To; //明显要快一点。
        else
          return S>t.S;
    }
};
priority_queue <Node> Q;
vector <Node> Edge[2501];
int m,n,Start,End,i[2501];
void Dijkstra()
{
    i[Start]=0;
    Q.push(Node(Start,i[Start]));
    while (!Q.empty())
    {
        Node t=Q.top();
        Q.pop();
        for (int a=0;a<Edge[t.To].size();a++)
        {
            Node T=Edge[t.To][a];
            if (i[T.To]>t.S+T.S)
            {
                i[T.To]=t.S+T.S;
                Q.push(Node(T.To,i[T.To])); //其实这才是更新,i[]不过是记录。
            }
        }
    }
}
int main() //Dijkstra+优先队列。
{
    memset(i,0x3f,sizeof(i));
    scanf("%d%d%d%d",&n,&m,&Start,&End);
    for (int a=0;a<m;a++)
    {
        int t,t1,t2;
        scanf("%d%d%d",&t1,&t2,&t);
        Edge[t1].push_back(Node(t2,t));
        Edge[t2].push_back(Node(t1,t));
    }
    Dijkstra();
    printf("%d",i[End]);
    return 0;
}

SPFA+SLF优化:

源代码:

#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm> 
using namespace std;
struct Node1
{
    int S,To,Next;
}Edge[12401];
struct Node2
{
    int X,Y,S;
}Map[12401];
deque <int> Q; //双端队列。
int m,n,Num(0),Start,End,i[2501],Sum[2501],Head[2501];
bool In[2501]={0};
void Add(int t1,int t2,int t)
{
    Edge[++Num].To=t2;
    Edge[Num].S=t;
    Edge[Num].Next=Head[t1];
    Head[t1]=Num;
}
int main() //SPFA+SLF+随机化排序,妈的谁还能卡我!
{
    memset(i,0x3f,sizeof(i));
    scanf("%d%d%d%d",&n,&m,&Start,&End);
    for (int a=0;a<m;a++)
      scanf("%d%d%d",&Map[a].X,&Map[a].Y,&Map[a].S);
    random_shuffle(Map,Map+m); //随机化排序。
    for (int a=0;a<m;a++)
    {
        Add(Map[a].X,Map[a].Y,Map[a].S);
        Add(Map[a].Y,Map[a].X,Map[a].S);
    }
    i[Start]=0;
    Q.push_back(Start);
    In[Start]=true;
    while (!Q.empty())
    {
        int t=Q.front();
        Q.pop_front();
        In[t]=false;
        for (int a=Head[t];a;a=Edge[a].Next)
        {
            int T=Edge[a].To;
            if (i[T]>i[t]+Edge[a].S)
            {
                Sum[T]=Sum[t]+1;
                if (Sum[T]>n) //判负环。
                  return 0;
                i[T]=i[t]+Edge[a].S;
                if (!In[T])
                {
                    In[T]=true;
                    if (!Q.empty()&&i[Q.front()]>i[T])
                      Q.push_front(T);
                    else
                      Q.push_back(T);
                }
            }
        }
    }
    printf("%d",i[End]);
    return 0;
}
原文地址:https://www.cnblogs.com/Ackermann/p/6023746.html