目录
1.租用游艇
2.邮递员送信
3.【模板】单源最短路径(标准版)
1.租用游艇
P1359 租用游艇 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
输入数据:
3 5 15 7
因为这道题数据不大,所有我们直接使用Floyd 算法。
这道题大家可能没看懂怎么存图,其实就是第x行的第y个元素,就是从x站到y站的租金,所以是一个半矩阵输入。
下面是完整AC代码:
#include<bits/stdc++.h>
#define inf 1234567890
using namespace std;
int a[201][201];
int main()
{
int n;
cin>>n;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)a[i][j]=inf;//初始化
for(int i=1;i<n;i++)
for(int j=i+1;j<=n;j++)
{
int x;
cin>>x;
a[i][j]=x;//邻边矩阵存图
}
for(int k=1;k<=n;k++)
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)//式子套用
a[i][j]=min(a[i][j],a[i][k]+a[k][j]);
cout<<a[1][n]<<endl;
return 0;
}
2.邮递员送信
P1629 邮递员送信 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
输入数据:
5 10 2 3 5 1 5 5 3 5 6 1 2 8 1 3 8 5 3 4 4 1 8 4 5 3 3 5 6 5 4 2
这道题需要建立一个返回的图,因为这是有向图,所以1到其他节点和其他节点到1的最短路径不一定是相同的。
使用Dijkstra 算法,我们可以给dis的数组开成两倍大小,这样可以将反图也建在同一个图上,也可以重新建图,但是这样前面的方法方便一些。
下面是完整AC代码:
#include<bits/stdc++.h>
#define M 500010
#define inf 1234567890
using namespace std;
struct edge{
int u,v,w,next;
}e[M];
struct node{
int w,now;
bool operator<(const node &k)const
{
return w>k.w;//堆优化,小的元素放在堆顶,大根堆
}
};
int head[M],re=0,n,m,s,v[M],dis[M];
priority_queue<node>q;
void add(int u,int v,int w)//链式前向星存图
{
e[++re].u=u;
e[re].v=v;
e[re].w=w;
e[re].next=head[u];
head[u]=re;
}
void dijkstra(int s)
{
for(int i=1;i<=n*2;i++) dis[i]=inf;//将点设置为无穷大
dis[s]=0;//起点设置为0
node p;
p.w=0,p.now=s;
q.push(p);
while(!q.empty()){
node k=q.top();
q.pop();
int u=k.now;
if(v[u]) continue;//如果遍历过,直接跳过循环
v[u]=1;
for(int i=head[u];i;i=e[i].next){//下一个点
int v=e[i].v;
if(dis[v]>dis[u]+e[i].w)//更新最小权重
{
dis[v]=dis[u]+e[i].w;
q.push((node){dis[v],v});
}
}
}
}
int main()
{
cin>>n>>m;
for(int i=0;i<m;i++){
int u,v,w;
cin>>u>>v>>w;//建边
add(u,v,w);
add(v+n,u+n,w);//建返回的图
}
dijkstra(1);//求出1到其他点的最短路径
int ans=0;
for(int i=1;i<=n;i++){
ans+=dis[i];
}
dijkstra(1+n);//求出其他点到1的最短的路径
for(int i=1+n;i<=n*2;i++){
ans+=dis[i];
}
cout<<ans<<endl;
return 0;
}
3.【模板】单源最短路径(标准版)
P4779 【模板】单源最短路径(标准版) - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
输入数据:
4 6 1 1 2 2 2 3 2 2 4 1 1 3 5 3 4 3 1 4 4
既然是模板题目,这里就直接出Dijkstra 算法来解决。
下面是AC完整代码:
#include<bits/stdc++.h>
#define M 500010
#define inf 1234567890
using namespace std;
struct edge{
int u,v,w,next;
}e[M];
struct node{
int w,now;
bool operator<(const node &k)const
{
return w>k.w;//堆优化,小的元素放在堆顶,大根堆
}
};
int head[M],re=0,n,m,s,v[M],dis[M];
priority_queue<node>q;
void add(int u,int v,int w)//链式前向星存图
{
e[++re].u=u;
e[re].v=v;
e[re].w=w;
e[re].next=head[u];
head[u]=re;
}
void dijkstra()
{
for(int i=1;i<=n;i++) dis[i]=inf;//将点设置为无穷大
dis[s]=0;//起点设置为0
node p;
p.w=0,p.now=s;
q.push(p);
while(!q.empty()){
node k=q.top();
q.pop();
int u=k.now;
if(v[u]) continue;//如果遍历过,直接跳过循环
v[u]=1;
for(int i=head[u];i;i=e[i].next){//下一个点
int v=e[i].v;
if(dis[v]>dis[u]+e[i].w)//更新最小权重
{
dis[v]=dis[u]+e[i].w;
q.push((node){dis[v],v});
}
}
}
}
int main()
{
cin>>n>>m>>s;
for(int i=0;i<m;i++){
int u,v,w;
cin>>u>>v>>w;//建边
add(u,v,w);
}
dijkstra();
for(int i=1;i<=n;i++){
cout<<dis[i]<<" ";
}
return 0;
}