hdu3339 In Action 最短路+01背包

//有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;
    }
}


你可能感兴趣的:(dijkstra,01背包)