L2-001 紧急救援
算法:Dijkstra(最短路) DFS
思路:先求出最短路的长度,再依据长度进行搜索。
注意:剪枝以及记录最多的救援队数。
#include<iostream>
#include<string>
#include<vector>
#include<queue>
using namespace std;
const int N = 505;//数据范围
int n, m, s, d, len;
int a[N], dis[N];
bool vis[N];
//邻接表存图
struct node {
vector<int>v, w;
}edge[N];
typedef pair<int, int> PII;//对组
int dijkstra()
{
memset(dis, 0x3f, sizeof(dis));
dis[s] = 0;
priority_queue<PII, vector<PII>, greater<PII> >q;
q.push(make_pair(dis[s], s));
while (!q.empty())
{
int u = q.top().second;
q.pop();
if (vis[u]) continue;
vis[u] = 1;
vector<int>& V = edge[u].v, & W = edge[u].w;//引用
for (int i = 0; i < V.size(); i++)
{
int v = V[i], w = W[i];
if (dis[v] > dis[u] + w)
{
dis[v] = dis[u] + w;
if (!vis[v])
q.push(make_pair(dis[v], v));
}
}
}
return dis[d];
}
int maxu = 0,ans = 0;//最多队伍数 最短路条数
string path;//路径
void dfs(int x,int sum,int step,string t)
{
if (step > len) return;//剪枝
if (x == d && step == len) {
ans++;
if (sum > maxu) {
maxu = sum;
path = t;
}
return;
}
vector<int>& V = edge[x].v, & W = edge[x].w;
for (int i = 0; i < V.size(); i++)
{
int v = V[i], w = W[i];
if (!vis[v]) {
vis[v] = 1;
dfs(v, sum + a[v], step + w, t + " " + to_string(v));
vis[v] = 0;
}
}
}
int main()
{
ios::sync_with_stdio(false);
cin >> n >> m >> s >> d;
for (int i = 0; i < n; i++)
{
cin >> a[i]; //读入每个城市救援队数量
}
for (int i = 0; i < m; i++)
{
int u, v, w;//出发城市 连接城市 边权
cin >> u >> v >> w;
edge[u].v.push_back(v); edge[u].w.push_back(w);
edge[v].v.push_back(u); edge[v].w.push_back(w);//双向边
}
//Dijkstra算法求最短路径
len = dijkstra();
memset(vis, 0, sizeof(vis));
dfs(s, a[s], 0, to_string(s));
cout << ans << ' ' << maxu << endl;
cout << path;
return 0;
}