这道题典型的求最短路径的算法,用Djktra算法写。关键点是要求出最短路径个数和最短路径中救援人员最多的人数,一开始想先求出最短距离再用DFS扫出最短路径,但在DFS中不好控制起点与终点路径扫描次序也会不同,递归的方法真的很绕人啊!
在Djktra算法中可以用在线处理的方法求出最短路径个数,当出现更短的路径时“重设”救援人数和路径计数,当出现相等路径时计数增加,救援人数如果更大再更新!
但发现一个问题,当我采用将当前最小的路径距离和最大的人数存起来再进行比对时无法ac。显示答案错误,
#include<iostream>
//#include<cstdio>
#define INF 65535
using namespace std;
int map[510][510];
void initialmap()
{
int i,j;
for(i=0;i<510;i++)
for(j=0;j<510;j++)
{
if(i==j)
map[i][j]=0;
else
map[i][j]=INF;
}
}
int findmin(int dist[],bool collect[],int n)
{
int i,min=INF,v=-1;
for(i=0;i<n;i++)
{
if(collect[i]==false&&dist[i]<min)
{
v=i;
min=dist[i];
}
}
return v;
}
int main()
{
int n,m,i,j,d,t,cnt[520]={0},s,tem=0;
int team[520]={0},dist[520],vetex[520]={0},weight[520]={0};
int min[520],wmax[520],tag=0;
bool collect[520];
int c1,c2;
//freopen("path.in.txt","r",stdin);
//freopen("path.out","w",stdout);
cin>>n>>m>>c1>>c2;
initialmap();
for(t=0;t<n;t++)
{
cin>>team[t];
}
while(m--)
{
cin>>i>>j>>d;
map[i][j]=d;
map[j][i]=d;
}
for(i=0;i<n;i++)
{
dist[i]=INF;
collect[i]=false;
vetex[i]=1;
min[i]=INF;
wmax[i]=0;
cnt[i]=1;
}
//t=team[c1];
weight[c1]=team[c1];
dist[c1]=0;
int v;
while(v!=c2)
{
v=findmin(dist,collect,n);
if(v==-1)
break;
collect[v]=true;
for(i=0;i<n;i++)
{
if(collect[i]==false&&map[v][i]!=INF)
{
if((map[v][i]+dist[v])<dist[i])
{
dist[i]=map[v][i]+dist[v];
weight[i]=team[i]+weight[v];
cnt[i]=cnt[v];
}
else
if((map[v][i]+dist[v])==dist[i])
{
cnt[i]+=cnt[v];
if(weight[i]<team[i]+weight[v])
weight[i]=team[i]+weight[v];
}
/*if(dist[i]<min[i])
{
min[i]=dist[i];
cnt[i]=cnt[v];
wmax[i]=weight[i];
}
else
if(dist[i]==min[i])
{
cnt[i]=cnt[i]+cnt[v];
if(weight[i]>wmax[i])
wmax[i]=weight[i];
}*/
// cout<<"--"<<v<<","<<i<<weight[i]<<endl;
/*if(i==c2)
tag=1;*/
}
}
/* if(tag==1)//一开始的想法,发现这样求出路径的个数c2之前的所有节点不可有俩条相同的最短路径才能正确
{
if(dist[c2]<min)
{
// cout<<cnt<<endl;
min=dist[c2];
wmax=weight[c2];
cnt=1;
}
else if(dist[c2]==min)
{
// cout<<"--"<<v<<endl;
if(weight[c2]>wmax)
wmax=weight[c2];
cnt++;
// cout<<"=="<<cnt<<endl;
}
}
tag=0;*/
}
cout<<cnt[c2]<<" "<<weight[c2];
return 0;
}