第六天PAT-A1018 Public Bike Management小根堆优化基于邻接表Dijkstra+DFS

A1018

Description:

公共自行车管理中心PBMC监控着城市所有自行车站的实时容量。如果一个站正好是半满状态则称之为完美状态。如果一个站满了或是空了,PBMC将相应将之调整为完美态。此外,在路上的所有站也将被调整。

当有问题反馈时,PBMC选择最短的路去向该站,如果有多条最短路径,则选择需要投递自行车数最少的那条。

算法描述:

  • 单源最短路Dijkstra找出最短路径
  • 深搜找出最短路径条数,与此同时记录下该条路径,正向遍历路径,在首个大于完美态的自行车站之前,将所需的自行车数累加,即必须要从PBMC带出的自行车数。首个大于完美态至终点节点,同样将自行车数相加并减去各站完美态的自行车数总和,若得数小于零,即后半段也需从PBMC带出自行车,累加即可,若大于零,则需待会,由两个变量minout、minback记录最小带出带回自行车数,然后更新答案路径。
  • 不知道为啥,小根堆优化下的基于邻接表Dijkstra+DFS最后一组样例始终超时,有空再回头看看吧。😅
#include<iostream>
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#include<string.h>
#include<algorithm>
#include<map>
#include<set>
#include<vector>
#include<queue>
using namespace std;
const int maxn = 505;
const int maxm = (maxn*maxn)/2;
const int inf = 0x3f3f3f3f;
struct edge{
    int t;
    int v;
    int next;
}e[maxm];
int p[maxn], eid;
int cmax, n, sp, m;
typedef pair<int, int>PII;
set<PII, less<PII>>minheap;
bool vst[maxn];
int dis[maxn];
int crt[maxn];
void init(){
    memset(p, -1, sizeof(p));
    memset(vst, false, sizeof(vst));
    memset(dis, 0x3f, sizeof(dis));
    eid = 0;
}
void ins(int u, int v, int t){
    e[eid].v = v;
    e[eid].t = t;
    e[eid].next = p[u];
    p[u] = eid++;
}
void in(int u, int v, int t){
    ins(u, v, t);
    ins(v, u, t);
}
bool dijkstra(){
    minheap.insert(PII(0, 0));
    dis[0] = 0;
    for(int i = 0; i <= n; i++){
        if(minheap.size() == 0)
            return false;
        set<PII, less<PII>>::iterator iter = minheap.begin();
        int u = iter->second;
        minheap.erase(*iter);
        vst[u] = true;
        for(int j = p[u]; j != -1; j = e[j].next){
            int v = e[j].v;
            if(!vst[v] && dis[u] + e[j].t < dis[v]){
                minheap.erase(make_pair(dis[v], v));
                dis[v] = dis[u] + e[j].t;
                minheap.insert(make_pair(dis[v], v));
            }
        }
    }
    return true;
}
vector<int> ans;
vector<int> record;
int minout = inf, minback = inf;
void dfs(int now, int totaltime, int level, int pre){
    if(now == sp){  //当前到达终点
        int out = 0, backcnt = 0, i;
        for(i = 0; i < level; i++){
            if(crt[record[i]] <= 0) out += abs(crt[record[i]]);
            else break;
        }
        for(int j = i; j < level; j++){
            backcnt += crt[record[j]];
        }
        if(backcnt <= 0){
            out += abs(backcnt);
            backcnt = 0;
        }
        if(out < minout || (out == minout && backcnt < minback)){
            minout = out;
            minback = backcnt;
            ans = record;
        }
        return ;    //无条件返回
    }
    if(totaltime >= dis[sp])    //当前没到达终点,但是用时过多
        return ;
    for(int i = p[now]; i != -1; i = e[i].next){
        if(e[i].v != pre && totaltime + e[i].t <= dis[sp]){
            record.push_back(e[i].v);
            dfs(e[i].v, totaltime + e[i].t, level+1, now);
            record.pop_back();
        }
    }
}
int main()
{
#ifdef ONLINE_JUDGE
#else
    freopen("1.txt", "r", stdin);
#endif // ONLINE_JUDGE
    scanf("%d%d%d%d", &cmax, &n, &sp, &m);
    cmax /= 2;
    init();
    for(int i = 1; i <= n; i++){
        scanf("%d", &crt[i]);
        crt[i] -= cmax;
    }
    int u, v, t;
    for(int i = 0; i < m; i++){
        scanf("%d%d%d", &u, &v, &t);
        in(u, v, t);
    }
    dijkstra();
    dfs(0, 0, 0, -1);
    printf("%d 0", minout);
    for(int i = 0; i < ans.size(); i++){
        printf("->%d", ans[i]);
    }
    printf(" %d\n", minback);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值