As an emergency rescue team leader of a city, you are given a special map of your country. The map shows several scattered cities connected by some roads. Amount of rescue teams in each city and the length of each road between any pair of cities are marked on the map. When there is an emergency call to you from some other city, your job is to lead your men to the place as quickly as possible, and at the mean time, call up as many hands on the way as possible.
作为一个城市的紧急救援队长,你会得到一张你所在国家的特殊地图。这张地图显示了几个分散的城市,由一些道路连接起来。每个城市的救援队伍数量和任何两个城市之间的每条道路的长度都在地图上标出。当你接到来自其他城市的紧急呼叫时,你的工作是带领你的人尽快赶到那个地方,与此同时,召集尽可能多的人在路上。
就是第一行四个数分别是节点数,行数,起点,终点。
第二行为各个城市的救护人员的人数
之后m行为公路的起点城市,终点城市,路程长度。
最后输出要求为:起点到终点的最短路径条数和最短路径中最多能获得的救护人员人数
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
这个可以说是,相当大的一道题了,首先,我们要一个点到另一个点的最短距离,而谈到这一点,迪杰斯特拉算法自然是第一选择,说来也是惭愧,我作为一名计算机本科生,上了三年了,之前遇到用迪杰斯特拉算法的地方很多,但是从来都是直接拿来主义,网上copy一个接口改改就直接用了,这回也算是心血来潮,想要手撸一回。
其实迪杰斯特拉算法的话,初次接触可能会觉得,这个很难很绕,不过我虽然没有自己手写过,但是理论我还是学的很透彻的,所以第一次手撸其实还算是比较顺利。
主要流程:首先,用map
大概的一个迪杰斯特拉算法的流程就是这样的了,不过我们还需要注意就是对于一个节点被选中了,他是从哪一个节点来的还是不同的,就比如我起点选中,那么路径本身就是距离,但是如果被其他的节点选中,那么到那个节点的距离也是要考虑的。所以我们又设置了juli数组用来存储我们到每一个选中节点的距离。
这样一来,我们的迪杰斯特拉算法就算是完成了。
此时,我们回过头来看,我们的题目要求中还要我们选择一个最短并且能够得到最多救援人员的路径,也就是途径的节点的权值和要最小的,那么我们就需要另起一个数组geted(别问,问就是随性取名法),用来记录每一个节点到这里能有多少救护人员,初始化起点,然后后续就是选中的节点本身+链接的那个节点的geted的数据就可以了(类似前缀和)。
这样看起来,我们似乎可以直接提交了,但是很遗憾,我们还是忽略了一点,导致我还是有一些样例错了,那就是他要我们给出的是最短路径数目,但是我们知道,我们这个思路找到最短之后就返回了,如果要改的话,动的代码会很多,所以我就灵机一动,改用DFS来解决这个问题。
我们有起点,终点,要的路径权值和,有图,直接DFS找长度和当前节点都达标的路径的种类就行,这个相比前面,我可太熟练了,这里也就不多说了。
最后,成功AC,也算是一道收货不少的题目了。
这里注释掉的都是调试的时候用到的一些输出,如果想细扣的话可以解开看一下。
#include
#include
using namespace std;
int juli[500]={0};
int geted[500]={0};
int zoufa=0;
map<int,vector<int>> ans;
int daan=0;
int visit2[500]={0};
void dfs(map<int,vector<int>> mp,int len,int tu[500][500],int zou,int now,int zhong)
{
if(zou==len&&now==zhong){
zoufa++;
return;
}
if(zou>len){
return;
}
for(int i=0;i<mp[now].size();i++){
if(visit2[mp[now][i]]==0){
visit2[mp[now][i]]=1;
dfs(mp,len,tu,zou+tu[now][mp[now][i]],mp[now][i],zhong);
visit2[mp[now][i]]=0;
}
}
}
int djstl(map<int,vector<int>> mp,int visit[500],int tu[500][500],int qi,int zhong,int n)
{
set<int> havedone;
while(visit[zhong]==0)
{
int num;int lengths=INT_MAX;int from;int ren;
for(int i=0;i<n;i++){
if(visit[i]==1){
for(int j=0;j<mp[i].size();j++){
if((tu[i][mp[i][j]]+juli[i]<lengths||(tu[i][mp[i][j]]+juli[i]==lengths&&geted[i]>=ren))&&visit[mp[i][j]]!=1){
if(tu[i][mp[i][j]]+juli[i]<lengths){
daan=1;
}
else{
daan++;
}
lengths=tu[i][mp[i][j]]+juli[i];
num=mp[i][j];
from=i;
ren=geted[i];
}
}
}
}
visit[num]=1;
geted[num]+=geted[from];
juli[num]=lengths;
//
// for(int i=0;i
// ans[num].push_back(ans[from][i]);
// }
//
// ans[num].push_back(num);
if(num==zhong){
// for(int i=0;i
// cout<
// }
dfs(mp,lengths,tu,0,qi,zhong);
cout<<zoufa<<" "<<geted[num]<<endl;
return lengths;
}
}
}
int main()
{
int m,n;
map<int,vector<int>> mp;
int qi;
int zhong;
int tu[500][500]={0};
cin>>n>>m>>qi>>zhong;
for(int i=0;i<n;i++){
cin>>geted[i];
vector<int> mid;
mp.insert(pair<int,vector<int>>(i,mid));
ans.insert(pair<int,vector<int>>(i,mid));
}
// cout<<"from?to?len?"<
for(int i=0;i<m;i++){
int from,to,len;
cin>>from>>to>>len;
mp[from].push_back(to);
mp[to].push_back(from);
tu[from][to]=len;tu[to][from]=len;
}
int visit[500]={0};
visit[qi]=1;visit2[qi]=1;
ans[qi].push_back(qi);
if(qi!=zhong){
djstl(mp,visit,tu,qi,zhong,n);
}
else{
cout<<"1"<<" "<<geted[qi]<<endl;
}
// cout<
// for(map>::iterator it=ans.begin();it!=ans.end();it++){
// if(it->second.size()!=0){
// for(int i=0;isecond.size();i++){
// cout<second[i]<<" ";
// }
// cout<
// }
// }
return 0;
}
//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
//5 5 0 4
//1 1 1 1 1
//0 1 1
//0 2 1
//1 3 1
//2 3 1
//3 4 1
//结果:2,4