题目描述
题目场景为:作为一个城市救援队队长,要求你在一个城市发生事故时,以最快的速度赶到目标城市。当到达城市的时间相同时,要从途经的每个城市带上尽可能多的救援队员。
题目给出了一个无向图,图的每个节点代表一个城市,节点之间的边代表城市之间的道路联系。每个节点有一个权重值,代表这个节点所可以调用的救援队人数;每条边有一个权重值,代表两个城市之间的距离。实际上是一个最短路径问题,要求两个城市之间的最短路径的条数,同时在求得的最短路径之中,计算出能够带上的最多的救援人数。
解题思路
一开始用最短路径(dijkstra)写的,后来在网上看到有人用dfs写,反而要简单很多。把两种算法都写了一下,列在下面。
1.最短路径算法
#include <iostream>
#include <cstring>
#include <climits>
#include <vector>
using namespace std;
int cnt=1;
int max_weight=0;//路径最短情况下,可以携带的最多人手
void getResult(vector<vector<int>> &prev,int *weight,int temp,int weight_temp)
{
if(prev[temp].empty())
max_weight=max_weight<weight_temp?weight_temp:max_weight;
else
cnt+=prev[temp].size()-1;
for(int i=0;i<prev[temp].size();++i)
getResult(prev,weight,prev[temp][i],weight_temp+weight[prev[temp][i]]);
}
void dijkstra(int **matrix,int *weight,int size,int st,int end)
{
int *dist=new int[size];
for(int i=0;i<size;++i)
dist[i]=INT_MAX;
bool *vis=new bool[size];
memset(vis,false,sizeof(bool)*size);
vector<vector<int>> prev(size);
dist[st]=0;
int temp=st;
for(int i=0;i<size;++i)
{
vis[temp]=true;
//更新距离
for(int j=0;j<size;++j)
{
if(!vis[j]&&matrix[temp][j]>0)
{
if(dist[j]>dist[temp]+matrix[temp][j])
{
dist[j]=dist[temp]+matrix[temp][j];
prev[j].clear();
prev[j].push_back(temp);
}
else if(dist[j]==dist[temp]+matrix[temp][j])
{
dist[j]=dist[temp]+matrix[temp][j];
prev[j].push_back(temp);
}
}
}
//取得最小值
int min=INT_MAX;
for(int j=0;j<size;++j)
{
if(!vis[j]&&dist[j]<min)
{
min=dist[j];
temp=j;
}
}
}
//获得每条路径的权重和,并取得最大权重
getResult(prev,weight,end,weight[end]);
cout<<cnt<<" "<<max_weight<<endl;
delete[] dist,vis;
}
int main()
{
int num_cities,num_roads,st,end;
cin>>num_cities>>num_roads>>st>>end;
int *weight=new int[num_cities];//权重数组,代表每个节点的人手数量
for(int i=0;i<num_cities;++i)
cin>>weight[i];
int **matrix=new int*[num_cities];//关联矩阵,表示各个节点间的联系及距离
for(int i=0;i<num_cities;++i)
{
matrix[i]=new int[num_cities];
memset(matrix[i],0,sizeof(int)*num_cities);
}
for(int i=0;i<num_roads;++i)
{
int stTemp,endTemp,dist;
cin>>stTemp>>endTemp>>dist;
matrix[stTemp][endTemp]=matrix[endTemp][stTemp]=dist;
}
dijkstra(matrix,weight,num_cities,st,end);
delete[] weight;
return 0;
}
2 dfs
#include <iostream>
#include <cstring>
#include <climits>
using namespace std;
int cnt=0;
int weight_max=0,dist_min=INT_MAX;
void dfs(int **matrix,int *weight,bool *vis,int size,int st,int end,int distTemp,int weightTemp)
{
if(st==end)
{
if(distTemp<dist_min)
{
dist_min=distTemp;
weight_max=weightTemp;
cnt=1;
}
else if(distTemp==dist_min)
{
if(weightTemp>weight_max)
weight_max=weightTemp;
++cnt;
}
}
for(int i=0;i<size;++i)
{
if(!vis[i]&&matrix[st][i]>0)
{
vis[i]=true;
dfs(matrix,weight,vis,size,i,end,distTemp+matrix[st][i],weightTemp+weight[i]);
vis[i]=false;
}
}
}
int main()
{
int num_cities,num_roads,st,end;
cin>>num_cities>>num_roads>>st>>end;
int *weight=new int[num_cities];//权重数组,代表每个节点的人手数量
for(int i=0;i<num_cities;++i)
cin>>weight[i];
int **matrix=new int*[num_cities];//关联矩阵,表示各个节点间的联系及距离
for(int i=0;i<num_cities;++i)
{
matrix[i]=new int[num_cities];
memset(matrix[i],0,sizeof(int)*num_cities);
}
for(int i=0;i<num_roads;++i)
{
int stTemp,endTemp,dist;
cin>>stTemp>>endTemp>>dist;
matrix[stTemp][endTemp]=matrix[endTemp][stTemp]=dist;
}
bool *vis=new bool[num_cities];
memset(vis,false,sizeof(bool)*num_cities);
vis[st]=true;
dfs(matrix,weight,vis,num_cities,st,end,0,weight[st]);
cout<<cnt<<" "<<weight_max<<endl;
delete[] weight;
return 0;
}