問題の意味
世界中からの観光客に大きな利便性を提供し、杭州市の公共自転車サービスがあります。一つは、どの駅で自転車をレンタルし、市内の他のステーションにそれを返すことがあります。
パブリック・バイク・マネジメント・センター(PBMC)は、すべてのステーションのリアルタイムの容量を監視し続けます。ステーションはにあると言われる完璧な、それは正確に半分満杯である場合、条件。ステーションがいっぱいまたは空の場合、PBMCは完璧にそのステーションの状態を調整するためにバイクを収集したり、送信します。そして、もっと、途中ですべてのステーションがうまくように調整されます。
問題ステーションが報告されている場合、PBMCは、常にそのステーションに到達するための最短パスを選択します。複数の最短経路、PBMCから送信された自転車の最小数が選択される必要とするものがある場合。
上図は一例を示しています。ステーションは、頂点によって表され、道路は、エッジに対応します。エッジ上の数から別のエンドステーションに到達するのに要する時間です。頂点の内側に書かれた数Sは、で保存バイクの現在の数であるS。各ステーションの最大容量で問題を解決するために10であることを考えるとS 3、我々は2つの異なる最短経路を有します。
- PBMC - > S 1 - > S我々は1から自転車を収集することができますので、この場合に、4台のバイクは、PBMCから送信されなければなりませんS 1、その後に5台の自転車を取るS 3両局は完璧な条件になりますように。
- PBMCは、 - > S 2 - > S 3.このパスはパス1と同じ時間を必要とするが、わずか3バイクがPBMCから送られ、従って選択されるものです。
入力仕様:
各入力ファイルには、1つのテストケースが含まれています。各場合について、最初の行は、4つの数字が含まれます。* C M A ** X *(≤100)を、常に偶数、各ステーションの最大容量です。N(≤500)、局の総数。* S ** P 、問題局のインデックス(ステーションは1から番号付けされている N 、及びPBMCは、頂点0で表されます)。そして M 、道路の数。二行目に含まれる N *非負数* Cを** iは(* iは = 1、⋯、N)ここで、各C * **私は* iは、それぞれ、* ** * Sでバイクの現在の数です。そして、Mのラインは、それぞれ3つの数字が含まれ、従ってください:S I 、 S jは、とT I jの時間記述T I jの betwenステーションを移動するのにかかる* Sを** I *と* S ** J *。行のすべての数字は、スペースで区切られます。
出力仕様:
各テストケースの場合は、1行にあなたの結果を印刷します。PBMCを送信しなければならないことを第一の出力バイクの数。0->:次に1つのスペース、出力形式のパスの後にS > - 1->⋯ SのP 。最後に、別のスペースの後、我々はの状態の後にPBMCを取り戻す必要があることにバイクの出力数のS pが完璧に調整されています。
なお、このようなAのパスが一意でない場合、出力我々はPBMCに取り戻す必要があることにバイクの最小数を必要とするもの。裁判官のデータは、そのようなパスが一意であることを保証します。
サンプル入力:
10 3 3 5
6 7 0
0 1 1
0 2 1
0 3 3
1 3 1
2 3 1
サンプル出力:
3 0->2->3 0
思考
Xianpaoのダイクストラ最短経路の0-> Sを得ました。
これ方法に、得られた経路が反転され、従って、その逆関数は、セットを書くこと。
徐々に再帰S 0から、パスで、最良のパスが得られます。この機能を書いている時点で、注意を払うには、車でPBMCからの数とPBMCバックの数を整理します。
アイデアは、データの最後のセットが終わっていないので、唯一の29点を得た、最適化であってもよく、
コード
#include <stdio.h>
#include <string>
#include <stdlib.h>
#include <iostream>
#include <vector>
#include <string.h>
#include <algorithm>
#include <cmath>
#include <map>
#include <queue>
#include <functional>
#include <limits.h>
using namespace std;
int C, N, S, M;
int num[500 + 10]; //记录每个车站的车辆
int maze[500 + 10][500 + 10]; //记录图
vector<int> path[500 + 10]; // 记录逆向的路径 S->...->0
vector<int> path2[500 + 10]; // 记录正向路径 0->...->S
int bto = INT_MAX, bfrom = INT_MAX; //分别记录最小的带去的车辆,和 最小的带走车辆
vector<int> ans; // 记录最佳路径
//用于将路径反转
void get_rode(int me, int pre){
if(me == 0) path[me].clear();
for(int i = 0; i < path[me].size(); i++){
get_rode(path[me][i], me);
}
path2[me].push_back(pre);
}
//dfs求最佳路径
void dfs(int p, int to, int from, vector<int>& anst){
if(p == S){
// 更新路径
if(to < bto){
bto = to;
bfrom = from;
ans = anst;
}
else if(to == bto && from < bfrom){
bfrom = from;
ans = anst;
}
}
for(int i = 0; i < path2[p].size(); i++){
anst.push_back(path2[p][i]);
// 足够
if(from + num[path2[p][i]] > C / 2) dfs(path2[p][i], to, num[path2[p][i]] - C / 2 + from, anst);
// 不够
else dfs(path2[p][i], to + C / 2 - num[path2[p][i]] - from, 0, anst);
anst.pop_back();
}
}
//求最短路径(逆向)
void dijkstra(int cc) {
int dist[500 + 10];
for (int i = 1; i <= N; i++){
dist[i] = maze[i][cc];
path[i].push_back(cc);
}
dist[cc] = 0;
bool vis[500 + 10];
memset(vis, 0, sizeof(vis));
vis[cc] = 1;
for (int i = 0; i <= N; i++) {
int mark = -1, mindis = 185273099;
for (int j = 0; j <= N; j++) {
if (!vis[j] && dist[j] < mindis) {
mindis = dist[j];
mark = j;
}
}
vis[mark] = 1;
for (int j = 0; j <= N; j++) {
if (!vis[j]) {
if(dist[j] > dist[mark] + maze[mark][j]){
path[j].clear();
path[j].push_back(mark);
dist[j] = dist[mark] + maze[mark][j];
}
else if(dist[j] == dist[mark] + maze[mark][j]){
path[j].push_back(mark);
}
}
}
}
}
int main() {
cin >> C >> N >> S >> M;
for(int i = 1; i <= N; i++){
cin >> num[i];
}
int s, e, d;
memset(maze, 11, sizeof(maze)); // 185273099
for(int i = 1; i <= M; i++){
cin >> s >> e >> d;
maze[s][e] = d;
maze[e][s] = d;
}
dijkstra(0);
for(int i = 0; i < path[S].size(); i++){
get_rode(path[S][i], S);
}
vector<int> anst;
anst.push_back(0);
dfs(0, 0, 0, anst);
cout << bto << " ";
for(int i = 0; i < ans.size(); i++){
if(i) cout << "->" ;
cout << ans[i];
}
cout << " " << bfrom << endl;
return 0;
}