简单的dfs(写成了最短路),写了一下午,纪念一下。。。
#include<stdio.h>
#include<string.h>
#include<string>
#include<iostream>
#include<queue>
#include<stack>
#include<math.h>
#include<string>
#include<algorithm>
#include<map>
using namespace std;
int C,N,S,M;
int save[510]; //每个点的车数
struct node{
int x;
int l;
};
vector<node>a[510];
struct point{ //一个暂时路径
int l; //路径长度
int x; //该路径当前节点
vector<int>r; //路径
int take; //到达该点需从起点携带的自行车
int off; //到达该节点获得的自行车
bool operator < (const point& t)const{
return l >= t.l;
}
};
void find(){
int path[510]; //保存最短路径长
memset(path,0x3f3f3f3f,sizeof(path));
bool book[510]; //记录已经经过的节点
//注意,已经经过了的节点仍有可能重走,因为每次搜是不同的路径
memset(book,false,sizeof(book));
point x;
x.x = 0;
x.l = 0;
x.off = x.take = 0;
x.r.push_back(0);
path[0] = 0;
priority_queue<point>q;
q.push(x);
point r;
r.l = 0x3f3f3f3f;
while(!q.empty()){
x = q.top();
q.pop();
if(x.l > r.l) break;
if(x.x == S && x.l <= r.l){
if(x.l < r.l){
r = x;
}
else{
if(x.take < r.take){
r = x;
}
else if(x.take == r.take ){
if(x.off < r.off){
r = x;
}
}
}
}
if(book[x.x] == false || (x.l == path[x.x])){ //该点没走过,或者同样短的路径长,则需要重走
book[x.x] = true;
for(int i=0;i<a[x.x].size();i++){
if(path[x.x] + a[x.x][i].l <= path[a[x.x][i].x]){
path[a[x.x][i].x] = path[x.x] + a[x.x][i].l;
point temp = x;
temp.l = path[a[x.x][i].x];
temp.x = a[x.x][i].x;
if(save[a[x.x][i].x] >= C/2){ //判断自行车是不足还是剩余
temp.off += save[a[x.x][i].x] - C/2;
}
else{
if(temp.off + save[a[x.x][i].x] >= C/2){
temp.off -= C/2 - save[a[x.x][i].x];
}
else{
temp.take += (C/2 - save[a[x.x][i].x] - temp.off);
temp.off = 0;
}
}
temp.r.push_back(a[x.x][i].x);
q.push(temp);
}
}
}
}
printf("%d ",r.take);
for(int i=0;i<r.r.size();i++){
printf("%d",r.r[i]);
if(i == r.r.size()-1) printf(" ");
else printf("->");
}
printf("%d\n",r.off);
}
int main(){
scanf("%d%d%d%d",&C,&N,&S,&M);
for(int i=1;i<=N;i++){
scanf("%d",&save[i]);
}
for(int i=0;i<M;i++){
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
node t;
t.x = x;
t.l = z;
a[y].push_back(t);
t.x = y;
a[x].push_back(t);
}
find();
return 0;
}