poj 3635 广搜 最短路

题意:有n(n<=1000)个城市,m(m<=10000)条边,第i个城市油价为pi  (pi<=100),每升油能行驶一公里,有q (q<=100)个询问,每个询问给出汽车油箱的容量c (c<=100),起点u,终点v,问从u到v最少花费是多少?

分析:每个城市加多少油是未知的,借鉴dijkstra算法,每个城市可以加1单位的油,也可以转移到其它城市,用优先级队列来存储,每次取费用最小的状态。

用b[i][j]表示到达点i,剩余油量为j的最小花费,避免无用计算。

一开始枚举了所有能加的油量,TLE。

 

 

const int N = 1001, M = 101;
int p[N], b[N][M];//b[i][j] 到达点i,剩余油量j的最小花费
int n, m, query;
int c, u, v, d;

int head[N], pos;
struct edge{
    int v, next, d;
}e[20005];

struct node{
    int v, now, cost;
};

struct cmp{
    bool operator()(node a, node b){
        return a.cost > b.cost;
    }
};

priority_queue<node, vector<node>, cmp> q;

void bfs(){
    memset(b, -1, sizeof b);
    while(!q.empty()) q.pop();
    node t, temp;
    t.cost = 0;  t.v = u;  t.now = 0;  q.push(t);  b[u][0] = 0;
    while(!q.empty()){
        t = q.top();  q.pop();
        if(b[v][0]!=-1 && b[v][0]<=t.cost) continue;
        if(b[t.v][t.now] < t.cost) continue;
        
        /*FOE(i, 1, c-t.now){//枚举能加的油量,超时。。
            temp.v = t.v;  temp.cost = t.cost + i*p[t.v];  temp.now = t.now + i;
            if(b[temp.v][temp.now] == -1 || b[temp.v][temp.now] > temp.cost){
                b[temp.v][temp.now] = temp.cost; q.push(temp);
            }
        }*/

        if(t.now < c){//加1单位油
            temp.v = t.v;  temp.cost = t.cost + p[t.v];  temp.now = t.now + 1;
            if(b[temp.v][temp.now] == -1 || b[temp.v][temp.now] > temp.cost){
                b[temp.v][temp.now] = temp.cost;   q.push(temp);
            }
        }

        for(int j = head[t.v]; j != -1; j = e[j].next){//转移到下一顶点
            if(e[j].d <= t.now){
                temp.v = e[j].v;  temp.cost = t.cost;  temp.now = t.now - e[j].d;
                if(b[temp.v][temp.now] == -1 || b[temp.v][temp.now] > temp.cost){
                    b[temp.v][temp.now] = temp.cost;   q.push(temp);
                }
            }
        }
    }

    if(b[v][0] == -1) printf("impossible\n");
    else printf("%d\n", b[v][0]);
}

int main(){
    #ifndef ONLINE_JUDGE
    freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    #endif

    memset(head, -1, sizeof head);
    scanf("%d%d", &n, &m);
    FOR(i, 0, n) scanf("%d", &p[i]);
    FOR(i, 0, m){
        scanf("%d%d%d", &u, &v, &d);
        e[pos].v = v;  e[pos].next = head[u];  e[pos].d = d;  head[u] = pos++;
        e[pos].v = u;  e[pos].next = head[v];  e[pos].d = d;  head[v] = pos++;
    }
    scanf("%d", &query);
    while(query--){
        scanf("%d%d%d", &c, &u, &v);
        bfs();
    }

    return 0;
}

 

转载于:https://www.cnblogs.com/ts65213/archive/2013/06/04/3117090.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值