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