解题思路:Dijkstra算法(单源最短路径)和0-1背包,但是要考虑重边
#include<stdio.h>
#include<vector>
#include<string.h>
#include<iostream>
using namespace std;
vector < pair<int, int> > G[105];
const int INF = 1000000;
int Dij[105];
int isVisit[105];
int City[105];
int f[1000002];
int S, N, M;
void Init(){
int i;
for(i = 0; i <= N; i++){
G[i].clear();
Dij[i] = INF;
}
memset(isVisit, 0, sizeof(isVisit));
memset(f, 0, sizeof(f));
}
void Dijkstra(int begin){
int i, v, weight;
Dij[begin] = 0;
while(isVisit[begin] == 0){
isVisit[begin] = 1;
for(i = 0; i < G[begin].size(); i++){
v = G[begin][i].first;
weight = G[begin][i].second;
if(Dij[v] > Dij[begin] + weight)
Dij[v] = Dij[begin] + weight;
}
int min_cost = INF;
for(i = 0; i <= N; i++){
if(!isVisit[i] && Dij[i] < min_cost){
min_cost = Dij[i];
begin = i;
}
}
}
}
int pack(){
int i, j;
for(i = 1; i <= N; i++){
for(j = S; j >= 0; j--){
if(j >= Dij[i])
f[j] = f[j] > f[j - Dij[i]] + City[i] ? f[j] : f[j - Dij[i]] + City[i];
}
}
return f[S];
}
int main(){
int T, i, max_cost;
scanf("%d", &T);
while(T--){
scanf("%d%d%d", &S, &N, &M);
Init();
for(i = 0; i < M; i++){
int x, y, len;
scanf("%d%d%d", &x, &y, &len);
G[x].push_back(make_pair(y, len));
G[y].push_back(make_pair(x, len));
}
for(i = 1; i <= N; i++)
scanf("%d", &City[i]);
Dijkstra(0);
max_cost = pack();
printf("%d\n", max_cost);
}
return 0;
}