饿。其实我是一个不太喜欢写博客的人拉,因为觉得有点点浪费时间,特别是网上能搜到的题解,更懒得写博客了
可是还是写下了这一题的题解博客
因为自从今年cccc比赛后一直准备蓝桥杯,昨天蓝桥杯刚比完,今天想休息一下,也有点无聊
而且蓝桥杯因为基本不怎么考这种图的,所以dijkstra这些的也基本没复习,导致cccc到现在三周了,我今天无聊点开我PAT上的提交代码发现自己居然有点看不懂自己写的这题了= =还自己理了一下思路
而且网上对这题的题解也基本是粘个代码就了事,还不如回顾下自己的代码,废话说的有点多,下面还是粘题目和题解吧
L2-001. 紧急救援
作为一个城市的应急救援队伍的负责人,你有一张特殊的全国地图。在地图上显示有多个分散的城市和一些连接城市的快速道路。每个城市的救援队数量和每一条连接两个城市的快速道路长度都标在地图上。当其他城市有紧急求助电话给你的时候,你的任务是带领你的救援队尽快赶往事发地,同时,一路上召集尽可能多的救援队。
输入格式:
输入第一行给出4个正整数N、M、S、D,其中N(2<=N<=500)是城市的个数,顺便假设城市的编号为0~(N-1);M是快速道路的条数;S是出发地的城市编号;D是目的地的城市编号。第二行给出N个正整数,其中第i个数是第i个城市的救援队的数目,数字间以空格分隔。随后的M行中,每行给出一条快速道路的信息,分别是:城市1、城市2、快速道路的长度,中间用空格分开,数字均为整数且不超过500。输入保证救援可行且最优解唯一。
输出格式:
第一行输出不同的最短路径的条数和能够召集的最多的救援队数量。第二行输出从S到D的路径中经过的城市编号。数字间以空格分隔,输出首尾不能有多余空格。
输入样例:4 5 0 3 20 30 40 10 0 1 1 1 3 2 0 3 3 0 2 2 2 3 2输出样例:
2 60 0 1 3
要考虑的其实就是边值最小,在边值一样的情况下考虑点值最大,然后考虑有几条路径到这的边值是一样最小的,同时记录下路径
下面贴下我的代码,因为我是学校机房写的提交的,现在在宿舍复制下来加了注释,所以缩进变成了两个空格= =无伤大雅
#include<iostream>
#include<vector>
#include<cstring>
#include<set>
#include<algorithm>
#include<stack>
using namespace std;
int road[501][501],last[501],people[501],human[501],walk[501],rewalk[501];//road代表两个城市的距离 last代表当前城市的上一条路是什么,用来最后输出最短路径 people表示那个城市原本有多少人 human表示起点到目前城市能聚集多少个人
int main() //walk表示从起点到目前城市最短路径是多少 rewalk表示从起点到目前城市的最短路径走法有几个
{
int N,M,S,D;
memset(road,-1,sizeof(road));
set<int> vis;
cin>>N>>M>>S>>D;
int tmpi;
for(int i=0;i<N;i++)
{
cin>>tmpi;
people[i]=tmpi;
human[i]=tmpi;
vis.insert(i);
walk[i]=0x7fffffff;
}
last[S]=-1;
walk[S]=0;
rewalk[S]=1;
for(int i=0;i<M;i++)
{
int be,en;
cin>>be>>en;
cin>>road[be][en];
road[en][be]=road[be][en];
}//这上面都是初始化数据
for(int now=S;vis.size()>0;vis.erase(now))//遍历所有城市
{
int Min=0x7fffffff;
for(int i=0;i<N;i++)//每次选择和当前城市相邻中路径最短的城市
{
if(walk[i]<Min&&vis.count(i)==1)
{
now=i;
Min=walk[i];
}
}
for(int i=now,j=0;j<N;j++)
{
if(road[i][j]!=-1)
{
if(walk[j]>road[i][j]+walk[now])//距离优先,如果距离近的优先更新数据
{
walk[j]=road[i][j]+walk[now];
last[j]=now;
human[j]=people[j]+human[now];
rewalk[j]=rewalk[now];
}
else if(walk[j]==road[i][j]+walk[now])//如果距离相等,目前到的方案数+1 如果到的人数比之前的多 还是更新人数和从哪里来的数据
{
rewalk[j]+=rewalk[now];
if(human[j]<people[j]+human[now])
{
last[j]=now;
human[j]=people[j]+human[now];
}
}
}
}
}
cout<<rewalk[D]<<" "<<human[D]<<endl;
stack<int> st;//用栈,倒序输出路径
st.push(D);
for(int i=D;last[i]!=-1;i=last[i])
st.push(last[i]);
cout<<st.top();
st.pop();
while(!st.empty())
{
cout<<" "<<st.top();
st.pop();
}
return 0;
}