题目大意:给出一张图,求从起点S到终点D的最短路径的条数,并且求出在这些最短路径中能达到的最大的点权之和。
常规的dijkstra求最短路径,然后用dfs得到最大的点权和及最短路径数。
AC代码如下:
#include <iostream>
#include <vector>
#include <algorithm>
#include <cstdio>
#include <cmath>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <cstring>
using namespace std;
const int MAXN = 510;
const int INF = 0x7FFFFFFF;
int G[MAXN][MAXN] = {0};
int weight[MAXN] = {0};
int d[MAXN] = {0};
bool visited[MAXN] = {false};
vector<int> pre[MAXN];
void dijkstra(int s, int N)
{
fill(d, d + MAXN, INF);
d[s] = 0;
for (int i = 0; i < N; ++i)
{
int u = -1, min = INF;
for (int j = 0; j < N; ++j)
{
if(d[j] < min && !visited[j])
{
u = j;
min = d[j];
}
}
if(u == -1) return;
visited[u] = true;
d[u] = min;
for (int k = 0; k < N; ++k)
{
if(!visited[k] && G[u][k] < INF && d[u] + G[u][k] < d[k])
{
d[k] = d[u] + G[u][k];
pre[k].clear();
pre[k].push_back(u);
}
else if(!visited[k] && G[u][k] < INF && d[u] + G[u][k] == d[k])
pre[k].push_back(u);
}
}
}
int optValue = 0;
int pathCount = 0;
vector<int> tmpPath;
void dfs(int v, int S)
{
if(v == S)
{
pathCount++;
tmpPath.push_back(v);
int value = 0;
for (int i = tmpPath.size() - 1; i >= 0; --i)
{
value += weight[tmpPath[i]];
}
if(optValue < value) optValue = value;
tmpPath.pop_back();
return;
}
tmpPath.push_back(v);
for (int i = 0; i < pre[v].size(); ++i)
{
dfs(pre[v][i], S);
}
tmpPath.pop_back();
}
int main()
{
fill(G[0], G[0] + MAXN * MAXN, INF);
int N, M, S, D;
cin >> N >> M >> S >> D;
for (int i = 0; i < N; ++i)
{
scanf("%d", &weight[i]);
}
for (int i = 0; i < M; ++i)
{
int u, v, l;
cin >> u >> v >> l;
G[u][v] = G[v][u] = l;
}
dijkstra(S, N);
dfs(D, S);
printf("%d %d", pathCount, optValue);
return 0;
}