当前位置: 代码迷 >> 综合 >> 1379:热浪(邻接表存图+优先队列维护)
  详细解决方案

1379:热浪(邻接表存图+优先队列维护)

热度:45   发布时间:2024-01-26 02:56:00.0

【题目描述】

德克萨斯纯朴的民眾们这个夏天正在遭受巨大的热浪!!!他们的德克萨斯长角牛吃起来不错,可是他们并不是很擅长生產富含奶油的乳製品。Farmer John此时以先天下之忧而忧,后天下之乐而乐的精神,身先士卒地承担起向德克萨斯运送大量的营养冰凉的牛奶的重任,以减轻德克萨斯人忍受酷暑的痛苦。

FJ已经研究过可以把牛奶从威斯康星运送到德克萨斯州的路线。这些路线包括起始点和终点先一共经过T (1 ≤ T ≤ 2,500)个城镇,方便地标号為1到T。除了起点和终点外的每个城镇由两条双向道路连向至少两个其它的城镇。每条道路有一个通过费用(包括油费,过路费等等)。

给定一个地图,包含C (1 ≤ C ≤ 6,200)条直接连接2个城镇的道路。每条道路由道路的起点Rs,终点Re (1 ≤ Rs ≤ T; 1 ≤ Re ≤ T),和花费(1 ≤ Ci ≤ 1,000)组成。求从起始的城镇Ts (1 ≤ Ts ≤ T)到终点的城镇Te(1 ≤ Te ≤ T)最小的总费用。

【输入】

第一行: 4个由空格隔开的整数: T, C, Ts, Te;

第2到第C+1行: 第i+1行描述第i条道路。有3个由空格隔开的整数: Rs, Re和Ci。

【输出】

一个单独的整数表示从Ts到Te的最小总费用。数据保证至少存在一条道路。

【输入样例】

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

【提示】

【样例说明】

5->6->1->4 (3 + 1 + 3)

【思想】

还是典型的dijkstra算法的问题,用邻接表存图更胜邻接矩阵一筹,用优先队列优化又要更胜一筹。

【邻接表(无优化)】

#include<bits/stdc++.h>
using namespace std;
struct node
{int to;int dis;int next;
};
node e[30005];
int f[3005],v[3005],head[3005],num,a,b,c,n,m,ss,ee;
void add(int from,int to,int dis)
{num++;e[num].to=to;e[num].dis=dis;e[num].next=head[from];head[from]=num;
}
int main()
{memset(f,127,sizeof(f));scanf("%d%d%d%d",&n,&m,&ss,&ee);for(int i=1;i<=m;i++){scanf("%d%d%d",&a,&b,&c);add(a,b,c);add(b,a,c);}f[ss]=0;for(int i=1;i<=n;i++){int mi=0x3f3f3f3f;int k=0;for(int j=1;j<=n;j++){if(v[j]==0&&f[j]<mi){mi=f[j];k=j;}}if(k==0) break;v[k]=1;int from=k;for(int j=head[from];j!=0;j=e[j].next){int to=e[j].to;int dis=e[j].dis;f[to]=min(f[to],f[from]+dis);}}printf("%d",f[ee]);
}

时间:
在这里插入图片描述

【优先队列优化】

#include<bits/stdc++.h>
using namespace std;
struct no
{int c;int b;friend bool operator < (no aa,no bb){return aa.c>bb.c;}
};
struct node
{int to;int dis;int next;
};
node e[30005];
int f[3005],v[3005],head[3005],num,a,b,c,n,m,ss,ee;
void add(int from,int to,int dis)
{num++;e[num].to=to;e[num].dis=dis;e[num].next=head[from];head[from]=num;
}
priority_queue<no> q;
int main()
{no bbb,aaa;aaa.c=100000000;aaa.b=1;memset(f,127,sizeof(f));scanf("%d%d%d%d",&n,&m,&ss,&ee);for(int i=1;i<=m;i++){scanf("%d%d%d",&a,&b,&c);add(a,b,c);add(b,a,c);}bbb.b=ss;bbb.c=0;f[ss]=0;for(int i=1;i<=n;i++){if(aaa.b!=ss){q.push(aaa);aaa.b++;}else{aaa.b++;q.push(bbb);}}while(!q.empty()){no u=q.top();if(v[u.b]){q.pop();continue;}v[u.b]=1;int k=u.b;for(int j=head[k];j!=0;j=e[j].next){int to=e[j].to;int dis=e[j].dis;f[to]=min(f[to],f[k]+dis);bbb.c=f[to];bbb.b=to;q.push(bbb);}}printf("%d",f[ee]);
}

时间:
在这里插入图片描述
数据一大,优化了三分之一。

(我的代码还是很啰嗦,需要改进,求各位大神指点指点)