您的位置:首页 > 其它

PAT 甲级 1003

2018-01-27 19:10 501 查看

PAT 1003

题目介绍:

给出城市的连接状况和每个城市的救援队伍的数量。给定起点和终点,求出起点到终点最短路径的个数,以及找出一条可以包含救援队最多的最短路径,输出最多可以累计的救援队的数目。

题目思路:

本题目很明显是一个Dijkstra的最短路算法,但是题目的真正考察点在于求解最短路的个数和在多条最短路径上求解出累计救援队伍数目最多的个数。路的条数和救援队伍的数目都采用累计求和的思想。Dijkstra算法的核心是把结点划分成两个集合:已经求得最短路径的和未求得最短路径的。这个关系用一个用一个不等式来维护,具体参考算法导论有关章节。在这里的最短路算法,利用到了堆优化,每次从最小堆中取出两个集合间的最短距离进行不等关系的维护。

如果可以缩短当前u->v的路径,那么,
dist[v]=dist[u]+w(u,v)
num[v]=team[v]+num[v]
表示
v
的救援队伍的总数是v自己的加上u之前累加的;
road[v]=road[u]
是因为u->v只有一条路,那么从原点到v还是等于从原点到u的数目。

如果遇到了
dist[v]=dist[u]+w(u,v)
的情况,说明还有还有从原点到v不经过u的路径的长度等于从原点到v经过u的路径的长度;那么,此时的
road[v]
肯定要加上
road[u]
的,才是更新后的路径的数目,即
road[v]+=road[u]
。注意,如果队伍数目的更新条件
num[it->v] <= num[t] + team[it->v]
,也就是说,如果有更多的队伍数目,才进行更新!

AC代码:

#include <bits/stdc++.h>
using namespace std;
const int MAXN = 503; // 最大的结点个数
const int INF = 10000000;
int N, M, BEGIN, END; // 结点个数,边个数,起点,终点
// team是每个城市的队伍个数,num是最短路上城市累计的个数,dist是最短路径,road是路径累加的个数
int team[MAXN], num[MAXN], dist[MAXN], road[MAXN];
bool flag[MAXN];       // 加入最短路的标记
struct Node {
int v, w;
};
vector<Node>G[MAXN];  // 建图

struct cmp {          // 自定义比较结构
bool operator()(const int& a, const int& b) {
return dist[a] > dist[b];
}
};

void Create() {
int u, v, w;
for(int i = 0; i < M; ++i) {
cin >> u >> v >> w;
Node tmp;
tmp.v = v;
tmp.w = w;
G[u].push_back(tmp);   // 注意是无向图!!!!!
tmp.v = u;
tmp.w = w;
G[v].push_back(tmp);
}
}

void Dijkstra(int u) {
for(int i = 0; i < N; ++i) {
dist[i] = INF;
num[i] = team[i];
flag[i] = false;
road[i] = 0;
}
dist[u] = 0;
road[u] = 1;
priority_queue<int, vector<int>, cmp>Q;
Q.push(u);
while(!Q.empty()) {
int t = Q.top();
Q.pop();
if(flag[t]) {
continue;
}
flag[t] = true;
for(auto it = G[t].begin(); it != G[t].end(); it++) {
if(flag[it->v]) {
continue;
} else if(dist[it->v] > dist[t] + it->w) {
dist[it->v] = dist[t] + it->w;
num[it->v] = team[it->v] + num[t];
road[it->v] = road[t];
Q.push(it->v);
} else if(dist[it->v] == dist[t] + it->w ) {
if(num[it->v] <= num[t] + team[it->v]) {
num[it->v] = num[t] + team[it->v];
}
road[it->v] += road[t];    // 路径加1
}
}
}
}

int main() {
cin >> N >> M >> BEGIN >> END;
for(int i = 0; i < N; ++i) {
cin >> team[i];
}
Create();
Dijkstra(BEGIN);
cout << road[END] << " " << num[END];
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: