先用dijkstra求出各点的最短路,然后就是一个很裸的背包了。
#include<cstdio>
#include<vector>
#include<cstring>
#include<queue>
#include<functional>
using namespace std;
const int maxn = 105;
const int inf = 0x3f3f3f3f;
int n,m,total;
int dp[10500];
int wgh[maxn];
int maps[maxn][maxn];
int dis[maxn];
bool vis[maxn];
queue<int> que;
void init(){
total = 0;
fill(dp,dp+10500,inf);
for(int i=0;i<maxn;i++){
for(int j=0;j<maxn;j++){
if(i == j) maps[i][j] = 0;
else maps[i][j] = inf;
}
}
}
void spfa(){
fill(dis,dis+n+1,inf);
fill(vis,vis+n+1,false);
dis[0] = 0;
vis[0] = true;
que.push(0);
while(!que.empty()){
int v = que.front();que.pop();
vis[v] = false;
for(int i=0;i<=n;i++){
if(dis[i] > dis[v] + maps[v][i]){
dis[i] = dis[v] + maps[v][i];
if(!vis[i]){
vis[i] = true;
que.push(i);
}
}
}
}
}
int main(){
int cas;
scanf("%d",&cas);
while(cas--){
init();
scanf("%d%d",&n,&m);
int a,b,c;
while(m--){
scanf("%d%d%d",&a,&b,&c);
maps[a][b] = maps[b][a] = min(maps[a][b],c);
}
for(int i=1;i<=n;i++){
scanf("%d",&wgh[i]);
total += wgh[i];
}
spfa();
dp[total] = 0;
for(int i=1;i<=n;i++){
for(int j=0;j<total;j++)
dp[j] = min(dp[j],dp[j+wgh[i]] + dis[i]);
}
int bound = (total % 2 == 0) ? total / 2 : total / 2 + 1;
int res = inf;
for(int j=0;j<bound;j++) res = min(res,dp[j]);
if(res == inf) printf("impossible\n");
else printf("%d\n",res);
}
return 0;
}