2022.2.13 练习 PAT 甲 1030 Travel Plan (原题链接)
题解一:
#include <bits/stdc++.h>
using namespace std;
const int MAX_NUM=510;
const int INF=0x3fffffff;
int n,m,s,D;
int d[MAX_NUM];//起点到各点的最短路径长度
int visit[MAX_NUM]={0};//标记是否已经访问
int G[MAX_NUM][MAX_NUM];//邻接矩阵,存放距离
int cost[MAX_NUM][MAX_NUM];//存放两点间的花费
int min_cost=INF;//最少花费
vector<int> pre[MAX_NUM];//每个结点所能产生的最短路径的前驱结点
void Dijkstra(int s)
{
fill(d,d+MAX_NUM,INF);
d[s]=0;
for(int i=0;i<n;i++)
{
int u=-1,MIN=INF;
for(int j=0;j<n;j++)
{
if(visit[j]==0 && d[j]<MIN)
{
u=j;
MIN=d[j];
}
}
if(u==-1)
return;
visit[u]=1;
//cout<<u<<" : ";
for(int v=0;v<n;v++)
{
if(visit[v]==0 && G[u][v]!=INF)
{
//cout<<v<<endl;
if( d[u]+G[u][v]<d[v] )
{
d[v]=d[u]+G[u][v];
pre[v].clear();
pre[v].push_back(u);
}
else if ( d[u]+G[u][v]==d[v] )
{
pre[v].push_back(u);
}
}
}
}
}
vector<int> path,tmp_path;
void DFS(int v)
{
if(v==s)//叶子结点等于起点
{
tmp_path.push_back(v);
int cost_tmp=0;
for(int i=tmp_path.size()-1;i>0;i--)
{
int id=tmp_path[i];
int id_next=tmp_path[i-1];
cost_tmp+=cost[id][id_next];
}
if(cost_tmp<min_cost)
{
min_cost=cost_tmp;
path=tmp_path;
}
tmp_path.pop_back();
return ;
}
tmp_path.push_back(v);
for(int i=0;i<pre[v].size();i++)
{
DFS(pre[v][i]);
}
tmp_path.pop_back();
}
int main()
{
std::ios::sync_with_stdio(false);
cin>>n>>m>>s>>D;
fill(G[0],G[0]+MAX_NUM*MAX_NUM,INF);//初始化邻接矩阵
fill(cost[0],cost[0]+MAX_NUM*MAX_NUM,INF);//初始化邻接矩阵
while(m--)
{
int c1,c2,dis,c;
cin>>c1>>c2>>dis>>c;
G[c1][c2]=G[c2][c1]=dis;
cost[c1][c2]=cost[c2][c1]=c;
}
Dijkstra(s);
DFS(D);
for(int i=path.size()-1;i>=0;i--)
{
cout<<path[i]<<" ";
}
cout<<d[D]<<" "<<min_cost;
return 0;
}
题解二:
#include <bits/stdc++.h>
using namespace std;
const int MAX_NUM=510;
const int INF=0x3fffffff;
int n,m,s,D;
int d[MAX_NUM];//起点到各点的最短路径长度
int visit[MAX_NUM]={0};//标记是否已经访问
int G[MAX_NUM][MAX_NUM];//邻接矩阵,存放距离
int cost[MAX_NUM][MAX_NUM];//存放两点间的花费
int cc[MAX_NUM];//从起点到某一点的最少花费
int pre[MAX_NUM];//从起点到抹一点的最短路径上该点的前一个顶点
int min_cost=INF;//最少花费
void Dijkstra(int s)
{
fill(d,d+MAX_NUM,INF);
fill(cc,cc+MAX_NUM,INF);
d[s]=0;
cc[s]=0;
for(int i=0;i<n;i++)
{
pre[i]=i; }
for(int i=0;i<n;i++)
{
int u=-1,MIN=INF;
for(int j=0;j<n;j++)
{
if(visit[j]==0 && d[j]<MIN)
{
u=j;
MIN=d[j];
}
}
if(u==-1)
return;
visit[u]=1;
for(int v=0;v<n;v++)
{
if(visit[v]==0 && G[u][v]!=INF)
{
if( d[u]+G[u][v]<d[v] )
{
d[v]=d[u]+G[u][v];
pre[v]=u;
cc[v]=cc[u]+cost[u][v];
}
else if ( d[u]+G[u][v]==d[v] && cc[v]>cc[u]+cost[u][v])
{
cc[v]=cc[u]+cost[u][v];
pre[v]=u;
}
}
}
}
}
void DFS(int s,int v)
{
if(v==s)
{
cout<<s<<" ";
return ;
}
DFS(s,pre[v]);
cout<<v<<" ";
}
int main()
{
std::ios::sync_with_stdio(false);
cin>>n>>m>>s>>D;
fill(G[0],G[0]+MAX_NUM*MAX_NUM,INF);//初始化邻接矩阵
fill(cost[0],cost[0]+MAX_NUM*MAX_NUM,INF);//初始化邻接矩阵
while(m--)
{
int c1,c2,dis,c;
cin>>c1>>c2>>dis>>c;
G[c1][c2]=G[c2][c1]=dis;
cost[c1][c2]=cost[c2][c1]=c;
}
Dijkstra(s);
DFS(s,D);
cout<<d[D]<<" "<<cc[D];
return 0;
}