//有n个电站,每一个电站能提供不同的power,
//所有tank从0点出发,停在该电站就代表摧毁了该电站,tank从电站到电站之间需要耗费能量
//现在有无穷的tank,问最少需要耗费多少油能够摧毁一半以上的power
//先用dijkstra求得到每个点的dis[i]
//然后用一个01背包得到答案
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std ;
const int maxm = 600010 ;
const int maxn = 110 ;
const int inf = 0x3f3f3f3f;
int dp[maxm] ;
struct Edge
{
int v , w ;
int next ;
}edge[maxm] ;
int head[maxn] ;
int v[maxn] ;
int nedge ;
int dis[maxn] ;
int vis[maxn] ;
int n , m ;
void addedge(int u , int v , int w)
{
edge[nedge].v = v ;
edge[nedge].w = w ;
edge[nedge].next = head[u] ;
head[u] = nedge++;
}
int dijkstra()
{
memset(vis , 0 ,sizeof(vis)) ;
for(int i = 1;i <= n;i++)
dis[i] = inf ;
dis[0] = 0 ;
int u = 0;
int sum = 0 ;
while(1)
{
int mi = inf ;int pos ;
for(int i = 0;i <= n;i++)
if(!vis[i] && dis[i] < mi)
mi = dis[pos = i] ;
if(mi == inf)break;
sum += mi ;
vis[pos] = 1;
for(int i = head[pos] ; i != -1 ;i = edge[i].next)
{
int v = edge[i].v ;
dis[v] = min(dis[v] , dis[pos] + edge[i].w) ;
}
}
return sum ;
}
int main()
{
// freopen("in.txt" ,"r" , stdin) ;
int T ;
scanf("%d" ,&T) ;
while(T--)
{
scanf("%d%d" ,&n , &m) ;
memset(head , -1 , sizeof(head)) ;
nedge = 0 ;
int sum = 0 ;
while(m--)
{
int u ,v , w ;
scanf("%d%d%d" ,&u , &v , &w) ;
addedge(u , v , w) ;
addedge(v , u , w) ;
}
for(int i = 1;i <= n;i++)
scanf("%d" ,&v[i]) ,sum+=v[i] ;
int tmp = dijkstra() ;
memset(dp , 0 , sizeof(dp)) ;
for(int i = 1;i <= n;i++)
{
if(dis[i] == inf)continue ;
for(int j = tmp ;j >= dis[i];j--)
dp[j] = max(dp[j] , dp[j-dis[i]] + v[i]) ;
}
int ans = inf;
for(int i = 0;i <= tmp ;i++)
if(dp[i] >= (sum)/2 + 1)
{
ans = i ;
break;
}
if(ans == inf)puts("impossible");
else
cout<<ans<<endl;
}
}
版权声明:本文为博主原创文章,未经博主允许不得转载。
时间: 2024-10-11 02:17:31