例一
cpp
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn=500;
const int INF=1000000000;
bool isin[maxn]={false};
int G[maxn][maxn];
int path[maxn],rescue[maxn],num[maxn];
int weight[maxn];
int citynum,roadnum,begins,e;
void Dijisktra(int a){
fill(path,path+maxn,INF);//记录最短距离
memset(rescue,0,sizeof(rescue));//记录点权
memset(num,0,sizeof(num));//记录最短路径的条数
path[a]=0;
rescue[a]=weight[a];
num[a]=1;
for(int i=0;i<citynum;i++){
int pi=-1,pv=INF;
for(int j=0;j<citynum;j++){
//找最短距离的结点
if(isin[j]==false&&path[j]<pv){
pi=j;
pv=path[j];
}
}
if(pi==-1) return;
isin[pi]=true;
for(int k=0;k<citynum;k++){
if(isin[k]==false&&G[pi][k]!=INF)
{
if(G[pi][k]+path[pi]<path[k])
{
path[k]=G[pi][k]+path[pi];
num[k]=num[pi];//更新最短路径数:不相同就覆盖
rescue[k]=rescue[pi]+weight[k];
}else
if(G[pi][k]+path[pi]==path[k]){
if(rescue[pi]+weight[k]>rescue[k])
rescue[k]=rescue[pi]+weight[k];//存大值
num[k]+=num[pi];//最短路径条数之和:相同累加
}
}
}
}
}
int main(){
int v1,v2;//顶点及边权-距离
fill(G[0],G[0]+maxn*maxn,INF);
cin>>citynum>>roadnum>>begins>>e;
for(int i=0;i<citynum;i++){
cin>>weight[i];//记录点权-救援小组数目
}
for(int j=0;j<roadnum;j++){
cin>>v1>>v2>>G[v1][v2];
//建立无向图
G[v2][v1]=G[v1][v2];
}
Dijisktra(begins);
cout<<num[e]<<" "<<rescue[e];
return 0;
}
例二
cpp
#include <iostream>
using namespace std;
const int maxn=100;
const int INF=1000000000;
bool isin[maxn]={false};
int G[maxn][maxn],expense[maxn][maxn];
int path[maxn],cost[maxn],pre[maxn];
int citynum,roadnum,b,e;
void Dijisktra(int a){//求最短路径
fill(path,path+maxn,INF);
fill(cost,cost+maxn,INF);
path[a]=0;
cost[a]=0;
for(int i=0;i<citynum;i++) pre[i]=i;
for(int i=0;i<citynum;i++){
int m=-1,mv=INF;
for(int j=0;j<citynum;j++){
if(isin[j]==false&&path[j]<mv){
m=j;
mv=path[j];
}
}
if(m==-1) return;
isin[m]=true;
for(int k=0;k<citynum;k++){
if(isin[k]==false&&G[m][k]!=INF)
{
if(G[m][k]+path[m]<path[k]){
path[k]=G[m][k]+path[m];
cost[k]=expense[m][k]+cost[m];
pre[k]=m;
}else if(G[m][k]+path[m]==path[k]){
if(cost[k]>expense[m][k]+cost[m])
cost[k]=expense[m][k]+cost[m];
pre[k]=m;
}
}
}
}
}
void DFSprint(int now){//打印
if(now==b){
cout<<now<<" ";
return;
}
DFSprint(pre[now]);
cout<<now<<" ";
}
int main(){
int v1,v2;
fill(G[0],G[0]+maxn*maxn,INF);
fill(expense[0],expense[0]+maxn*maxn,INF);
cin>>citynum>>roadnum>>b>>e;
for(int i=0;i<roadnum;i++){
cin>>v1>>v2>>G[v1][v2]>>expense[v1][v2];
G[v2][v1]=G[v1][v2];
expense[v2][v1]=expense[v1][v2];
}
Dijisktra(b);
DFSprint(e);
cout<<path[e]<<" "<<cost[e]<<endl;
return 0;
}
拓展
用迪杰斯特拉+DFS求最短路径的方法
关键代码:
cpp
const int maxn=100;
const int INF=10000000000;
bool isin[maxn]={false};
int G[maxn][maxn],num;
int path[maxn],w[maxn];
vector<int> pre[maxn];//记录最短路径的前驱:考虑会有多个
vector<int> minPath,temPath;//只记录最优或当前路径
void Dijisktra(int a){
fill(path,path+maxn,INF);
path[a]=0;
for(int i=0;i<num;i++){
int m=-1,mv=INF;
for(int j=0;j<num;j++){
if(isin[j]==false&&path[j]<mv){
m=j;
mv=path[j];
}
}
if(m==-1) return;
isin[m]=true;
for(int k=0;k<num;k++){
if(isin[k]==false&&G[m][k]!=INF)
{
if(G[m][k]+path[m]<path[k]){
path[k]=G[m][k]+path[m];
//找到更优路径,清空,装最短的
pre[k].clear();
//m结点加入k结点的前驱列表中,即为pre[k][i]==m;
pre[k].push_back(m);
}else if(G[m][k]+path[m]==path[k]){
//此时有多条最短路径,即存在多个前驱结点,直接加入即可
pre[k].push_back(m);
}
}
}
}
}
void DFSprint(int now,int begins){
int optValue=0;
if(now==begins){
temPath.push_back(begins);
if(value>optValue){//更新最优
optValue=value;
minPath=temPath;
}
temPath.pop_back();//弹出第一个
return;
}
temPath.push_back(now);
for(int i=0;i<pre[now].size();i++){
//遍历当前结点的前驱结点
DFSprint(pre[now][i]);//不断递归now结点的前驱列表
}
temPath.pop_back();//依次弹出第二个.....
}
//计算边权和
int edge=0;
for(int i=temPath.size()-1;i>0;i--){
int now=temPath[i],next=temPath[i-1];
edge+=G[now][next];//计算边权
}
//计算点权和
int weight=0;
for(int i=temPath.size()-1;i>0;i--){
int now=temPath[i];//当前结点下标
weight+=w[now];
}
例二:Dijiskatra+DFS
cpp
#include <iostream>
#include <vector>
using namespace std;
const int maxn=100;
const int INF=100000000;
bool isin[maxn]={false};
int G[maxn][maxn],expense[maxn][maxn];
int path[maxn],minValue=INF;
vector<int> pre[maxn],temPath,minPath;
int citynum,roadnum,b,e;
void Dijisktra(int a){
fill(path,path+maxn,INF);
path[a]=0;
for(int i=0;i<citynum;i++){
int m=-1,mv=INF;
for(int j=0;j<citynum;j++){
if(isin[j]==false&&path[j]<mv){
m=j;
mv=path[j];
}
}
if(m==-1) return;
isin[m]=true;
for(int k=0;k<citynum;k++){
if(isin[k]==false&&G[m][k]!=INF){
if(path[m]+G[m][k]<path[k]){
path[k]=path[m]+G[m][k];
pre[k].clear();
pre[k].push_back(m);
}else if(path[m]+G[m][k]==path[k]){
pre[k].push_back(m);
}
}
}
}
}
void DFSprint(int now){
int tempValue=0;
if(now==b){
temPath.push_back(now);
for(int i=temPath.size()-1;i>0;i--){
int v1=temPath[i],v2=temPath[i-1];
tempValue+=expense[v1][v2];
}
if(tempValue<minValue){
minValue=tempValue;
minPath=temPath;
}
temPath.pop_back();//出队
}
temPath.push_back(now);
for(int i=0;i<pre[now].size();i++){
DFSprint(pre[now][i]);
}
temPath.pop_back();
}
int main(){
int v1,v2;
fill(G[0],G[0]+maxn*maxn,INF);
fill(expense[0],expense[0]+maxn*maxn,INF);
cin>>citynum>>roadnum>>b>>e;
for(int i=0;i<roadnum;i++){
cin>>v1>>v2>>G[v1][v2]>>expense[v1][v2];
G[v2][v1]=G[v1][v2];
expense[v2][v1]=expense[v1][v2];
}
Dijisktra(b);
DFSprint(e);
for(int i=minPath.size()-1;i>=0;i--)
cout<<minPath[i]<<" ";
cout<<path[e]<<" "<<minValue<<endl;
return 0;
}