トピック
都市の緊急救助チームのリーダーとして、あなたにはあなたの国の特別な地図が与えられます。地図には、いくつかの散在する都市がいくつかの道路でつながっていることが示されています。各都市の救助チームの数と、都市間の各道路の長さが地図上にマークされます。他の都市から緊急通報があった場合、あなたの仕事は部下をできるだけ早くその場所に誘導し、その間に途中でできるだけ多くの人たちを呼び寄せることです。
入力仕様:
各入力ファイルには 1 つのテスト ケースが含まれています。各テスト ケースの最初の行には 4 つの正の整数が含まれます: N (≤500) - 都市の数 (都市には 0 から N-1 までの番号が付けられます)、M - 道路の数、C1 と C2 - 都市それぞれ、現在いる状態と保存する必要があるものを示します。次の行には N 個の整数が含まれており、i 番目の整数は i 番目の都市の救助チームの数です。次に M 行が続き、それぞれが 3 つの整数 c1、c2、L で道路を記述します。これらはそれぞれ、道路で接続されている都市のペアとその道路の長さです。C1 から C2 へのパスが少なくとも 1 つ存在することが保証されます。
出力仕様:
各テスト ケースについて、2 つの数値を 1 行に出力します。C1 と C2 の間の異なる最短パスの数と、収集できる救助チームの最大数です。行内のすべての数値は 1 つのスペースで区切る必要があり、行末に余分なスペースを含めることはできません。
サンプル
入力:
5 6 0 2
1 2 1 5 3
0 1 1
0 2 2
0 3 1
1 2 1
2 4 1
3 4 1
出力
2 4
質問分析
インターネット上にあるのはほとんどがダイクストラですが、以前Guo Wei先生のアルゴリズムの授業を見ていて、DFSを使った非常に似た問題があったので、すぐにDFSで書きたかったのですが、完了するまでに5時間近くかかりました。本当に美味しすぎますO(╥﹏╥)o。
最大救助者数を考慮した最短経路問題がテーマです。ここでの質問の条件に特に注意してください。最短経路は複数存在する場合があります。その中で最も救助者の数が多い経路を選択してください。したがって、DFS は判定の終点に到達したときに、まず経路の長さを判定してから、人数を操作する必要があります。
もう一つわかりにくい点がありますが、質問には都市間の道路が一方通行であるとは書かれていないので、道路データを保存する際には、ポジティブグループとネガティブグループを保存する必要があります。この状態で頭を悩ませたのですが、質問の種類が足りなかったのか、問題を見つけるまでに時間がかかりました。
コード
#include <iostream>
#include <cstring>
#include <vector>
#include <algorithm>
using namespace std;
struct Road
{
int endr, length;
};
int n, m, start, target;
int resnum[501]; //存放每个城市的救援人数
vector<vector<Road> > allroad(501);
int visited[501];
int maxres; //最大人数
int minlen; //最短路径
int minlennum; //最短路径的数量
int totalres; //当前人数
int totallen; //当前路长
void dfs(int point)
{
if (point == target) {
if (totallen < minlen) {
//有更短的路径
minlen = totallen; //更新最短路径
maxres = totalres; //更新该路径下的最大人数
minlennum = 1; //总数重新置为1
}
else if (totallen == minlen) {
//有多条最短路径
++minlennum;
maxres = max(totalres, maxres);
}
return;
}
//对从point出发的每一条路进行DFS
for (unsigned int i = 0; i < allroad[point].size(); i++)
{
if (totallen > minlen) {
//一个小剪枝,当前路径已经大于记录的最短路径,直接返回
return;
}
Road r = allroad[point][i];
if (!visited[r.endr]) {
visited[r.endr] = 1;
totallen += r.length;
totalres += resnum[r.endr];
dfs(r.endr);
visited[r.endr] = 0;
totallen -= r.length;
totalres -= resnum[r.endr];
}
}
}
int main()
{
cin >> n >> m >> start >> target;
for (int i = 0; i < n; i++)
{
int resque;
cin >> resque;
resnum[i] = resque;
}
for (int i = 0; i < m; i++)
{
int a;
Road temp1, temp2;
cin >> a >> temp1.endr >> temp1.length;
temp2.endr = a;
temp2.length = temp1.length;
allroad[a].push_back(temp1); //正向道路
allroad[temp1.endr].push_back(temp2); //反向道路
}
//初始化各种数据
memset(visited, 0, sizeof(visited));
visited[start] = 1;
maxres = 0;
minlen = 1 << 30;
totallen = 0;
totalres = resnum[start];
dfs(start);
cout << minlennum << " " << maxres;
return 0;
}