PAT.1003 Emergency - Dijikstra
题目链接
还就那个很久没写算法题,今天开始刷一下PAT甲级题库,权当复健。
不想写Dijikstra
这样写的问题在于由于起点是不定的,按照路的顺序遍历可能导致当前两个点都不可达,因此在遍历到起点相关的路之前的路会全部作废,(而且忽略了双向的问题)
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int cityCnt,roadCnt,start,des;
int minDis[505],minDisCnt[505],maxWeight[505],weights[505];
int main(){
memset(minDis,0x3f3f3f3f,sizeof(minDis));
cin>>cityCnt>>roadCnt>>start>>des;
for(int i = 0 ; i < cityCnt ; ++i){
cin>>weights[i];
maxWeight[i] = weights[i];
}
minDis[start] = 0;
for(int i = 0 ; i < roadCnt ; ++i){
int ts,td,tl;
cin>>ts>>td>>tl;
if(minDis[ts] + tl < minDis[td]){
minDisCnt[td] = 0;
minDis[td] = minDis[ts] + tl;
maxWeight[td] = maxWeight[ts] + weights[td];
}else if(minDis[ts] + tl == minDis[td]){
minDisCnt[td]++;
maxWeight[td] = max(maxWeight[td],maxWeight[ts] + weights[td]);
}
}
cout<<minDisCnt[des]+1<<' '<<maxWeight[des];
}
乖乖写
用小顶堆做优化。虽然因为这道题要统计最短路的最大人数,小顶堆也没好多少,但顺手还是这么写了。
用结构体来表示城市,两个属性(编号,到起点的(最小)距离)。
需要注意的地方是:
- 当 当前节点距起点距离 + 路径长度 == 目标节点距起点距离的情况,显然出现这种情况时,目标节点已经到达过了,所以只需要更新最大人数,而不需要判断是否到达,也无需再加入优先队列。
- 更新目标节点的最大人数时,应当根据当前节点的最大人数来更新。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int cityCnt,roadCnt,start,des;
//要维护所有的双向路,以及每个城市可达的城市,每个城市的权重,以及最短重复的次数
int paths[505][505],vis[505],weights[505],minDisCnt[505],minDis[505],maxWeights[505];
vector<int> neighbors[505];
struct node{
int city;
//当前城市到起点的距离
int disFromStart;
bool operator < (const node &a) const{
return disFromStart > a.disFromStart;
}
node(int city, int disFromStart){
this->city = city;
this->disFromStart = disFromStart;
}
};
int main(){
cin>>cityCnt>>roadCnt>>start>>des;
for(int i = 0 ; i < cityCnt ; ++i){
cin>>weights[i];
}
for(int i = 0 ; i < roadCnt ; ++i){
int ts,td,tl;
cin>>ts>>td>>tl;
paths[ts][td] = paths[td][ts] = tl;
neighbors[ts].push_back(td);
neighbors[td].push_back(ts);
}
memset(minDis,0x3f3f3f3f,sizeof(minDis));
maxWeights[start] = weights[start];
minDisCnt[start] = 1;
priority_queue<node> reachableCity;
reachableCity.push(node(start,0));
while(!reachableCity.empty()){
node currentNode = reachableCity.top();
int currentCity = currentNode.city;
int currentDis = currentNode.disFromStart;
reachableCity.pop();
if(vis[currentCity] != 0) continue;
vis[currentCity] = 1;
//检查当前节点的可达节点
for(int desCity : neighbors[currentCity]){
int desPathDis = paths[currentCity][desCity];
int desDisFromStart = desPathDis + currentDis;
if(vis[desCity] == 0 && desDisFromStart < minDis[desCity]){
minDisCnt[desCity] = minDisCnt[currentCity];
minDis[desCity] = desDisFromStart;
maxWeights[desCity] = maxWeights[currentCity] + weights[desCity];
reachableCity.push(node(desCity,desDisFromStart));
}else if(desDisFromStart == minDis[desCity]){
minDisCnt[desCity] += minDisCnt[currentCity];
maxWeights[desCity] = max(maxWeights[desCity],maxWeights[currentCity] + weights[desCity]);
}
}
}
cout<<minDisCnt[des]<<' '<<maxWeights[des];
}