HDU 3339 In Action

题目大意:有n个电站,每个电站都有一定的电量,电站之间有一定距离,我们要从0点出发去占领一些电站,使得占领的电站电量之和超过总电量的一半,求达到条件所要走的最短距离。如果可能的话,输出距离,否则输出不可能。

题解:首先计算所有点到起点的最短路,就得到了代价,现在又有价值,那么就是一个01背包~

#include <cstdio>   
#include <cstring>  
#include <utility>  
#include <queue>  
#include <algorithm>
using namespace std;  
const int N=20005;  
const int INF=~0U>>1;  
typedef pair<int,int>seg;  
priority_queue<seg,vector<seg>,greater<seg> >q;     
int sumv,sum,va[N],f[N],begin,end,d[N],head[N],u[N],v[N],w[N],next[N],n,m,a,b,c; 
bool flag,vis[N];  
void build(){  
    memset(head,-1,sizeof(head)); 
    for(int e=1;e<=m;e++){  
        scanf("%d%d%d",&u[e],&v[e],&w[e]);  
        u[e+m]=v[e]; v[e+m]=u[e]; w[e+m]=w[e];  
        next[e]=head[u[e]]; head[u[e]]=e;  
        next[e+m]=head[u[e+m]]; head[u[e+m]]=e+m;  
    }  
}     
void Dijkstra(int src){  
    memset(vis,0,sizeof(vis));  
    for(int i=0;i<=n;i++) d[i]=INF;  
    d[src]=0;  
    q.push(make_pair(d[src],src));  
    while(!q.empty()){  
        seg now=q.top(); q.pop();  
        int x=now.second;  
        if(vis[x]) continue; vis[x]=true;  
        for(int e=head[x];e!=-1;e=next[e]) 
        if(d[v[e]]>d[x]+w[e]){  
            d[v[e]]=d[x]+w[e];  
            q.push(make_pair(d[v[e]],v[e]));  
        }   
    }  
}      
void ZeroOnePack(int n,int v){
     memset(f,0,sizeof(f));
     for(int i=0;i<=n;i++)
         for(int j=v;j>=d[i];j--)
             f[j]=max(f[j],f[j-d[i]]+va[i]);
}
int main(){  
    scanf("%d",&n);
    while(~scanf("%d%d",&n,&m)){
        int sum=sumv=0;
        build();
        Dijkstra(0);
        for(int i=1;i<=n;i++)scanf("%d",&va[i]),sumv+=va[i];
        for(int i=1;i<=n;i++)if(d[i]!=INF)sum+=d[i];
        ZeroOnePack(n,sum); 
        flag=false;
        if ((sumv&1)==0) sumv=sumv>>1;
        else sumv=(sumv>>1)+1;
        for(int i=0;i<=sum;i++){
            if(f[i]>=sumv){
                printf("%d\n",i); 
                flag=true; break;
            }
        }
        if(!flag)puts("impossible");
    }  
    return 0;  
}
posted @ 2014-03-23 19:16  forever97  阅读(201)  评论(0编辑  收藏  举报