涉及知识点:
solution:
- (这个题有两种做法第一种是Dijkstra + DFS)
- (这个做法呢,这个解法是:我们把所有的最短路求出来,然后再根据救援人数最多进行深搜,回溯)
- (另一个是 Dijkstra + 记录)
- (代码我已经把重要的难以理解的地方加上了注释)
- (由于N的范围是500,那么我们可以判定这个图为稠密图,需要用邻接矩阵来存,当然如果用邻接表来存的话,那就需要用对优化的Dijkstra)
- (最好是用邻接表来存)
- (如果t这个点可以更新v这个点,那么到达v的路径,就应该和到达t的路径一样,人数就应该是到达t的总人数加上在v的总人数)
- (并且v的前驱就是t,pre[v] = t)
- (如果此时t到v的距离和原点到达v的距离相等,那么在v的路径总数应该是nums[v]+=nums[t])
- (如果人数可以更新的话,那么我们就更新一下总人数,pre[v] = t,w[v] = w[t] + weights[v])
std:
#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;
const int N = 510;
int n,m;
int dist[N];
bool st[N];
int weights[N];
int g[N][N];
int w[N];
int start,en;
vector<int>pre[N];// 记录所有的最短路径是怎么走的
void Dijkstra()
{
memset(dist,0x3f,sizeof dist);
dist[start] = 0;
for(int i = 0;i < n;i++)
{
int t = -1;
for(int j = 0;j < n;j++)
{
if(!st[j]&&(t==-1||dist[t]>dist[j]))t = j;
}
if(t==-1)return;
st[t] = true;
for(int v = 0;v < n;v++)
{
// 如果当前这个点t可以更新v这个点,那么,v的前驱就是t,由于v之前可能有别的前驱,所以我们需要把pre[v],清空
if(dist[v] > dist[t] + g[t][v])
{
dist[v] = dist[t] + g[t][v];
pre[v].clear();
pre[v].push_back(t);
} // t为v的前驱之一
else if(dist[v] == dist[t] + g[t][v])
{
pre[v].push_back(t);
}
}
}
}
vector<int>path;//记录答案
vector<int>tempPath;// 记录临时答案
int val = 0;// 记录最大人数
int cnt = 0;// 记录最短路的条数
void dfs(int v)
{
tempPath.push_back(v);// 把当前点放到vector里面
if(v == start)
{
cnt++;
int value = 0;
for(auto &x : tempPath)
{
value += weights[x];
}
if(value > val)
{
val = value;
path = tempPath;
}
tempPath.pop_back();
return;
}
for(auto &x : pre[v])
{
dfs(x);
}
tempPath.pop_back();//回溯
}
int main()
{
ios::sync_with_stdio(false);
cin >> n >> m >> start >> en;
memset(g,0x3f,sizeof g);
for(int i = 0;i < n;i++)
{
cin >> weights[i];
}
for(int i = 0;i < m;i++)
{
int a,b,c;
cin >> a >> b >> c;
g[a][b] = g[b][a] = min(g[a][b],c);
}
Dijkstra();
for(auto &x : pre[en])
{
dfs(x);
}
cout << cnt <<" " << val + weights[en] << endl;
int size = path.size();
for(int i = size - 1;~i;i--)
{
cout << path[i] << " ";
}
cout << en;
return 0;
}
// 第二种做法
#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;
const int N = 510;
int n,m;
int dist[N];
int pre[N];
bool st[N];
int nums[N];
int weights[N];
int g[N][N];
int w[N];
int start,en;
void Dijkstra()
{
memset(dist,0x3f,sizeof dist);
dist[start] = 0;
w[start] = weights[start];
for(int i = 0;i <= n;i++)
{
pre[i] = i;
}
nums[start] = 1;
for(int i = 0;i < n;i++)
{
int t = -1;
for(int j = 0;j < n;j++)
{
if(!st[j]&&(t==-1||dist[t]>dist[j]))t = j;
}
if(t==-1)return;
st[t] = true;
for(int v = 0;v < n;v++)
{
if(dist[v] > dist[t] + g[t][v])
{
dist[v] = dist[t] + g[t][v];
nums[v] = nums[t];
w[v] = w[t] + weights[v];
pre[v] = t;
}
else if(dist[v] == dist[t] + g[t][v])
{
nums[v] = nums[t] + nums[v];
if(w[t] + weights[v] > w[v])
{
pre[v] = t;
w[v] = w[t] + weights[v];
}
}
}
}
}
vector<int>road;
void dfs(int e)
{
if(e==start){
road.push_back(e);return ;
}
dfs(pre[e]);
road.push_back(e);
}
int main()
{
ios::sync_with_stdio(false);
cin >> n >> m >> start >> en;
memset(g,0x3f,sizeof g);
for(int i = 0;i < n;i++)
{
cin >> weights[i];
}
for(int i = 0;i < m;i++)
{
int a,b,c;
cin >> a >> b >> c;
g[a][b] = g[b][a] = min(g[a][b],c);
}
Dijkstra();
cout << nums[en] << " " << w[en] << endl;
bool tf = false;
dfs(en);
for(auto &x : road)
{
if(tf)cout << " ";
cout << x;
tf = true;
}
return 0;
}