题目详情 - L2-001 紧急救援 (25 分) (pintia.cn)
题解:使用dijkstra算法就可以了,难点在于如何存储路径。我首先十分单纯的用了pair<int,int>进行优化,直接WA了。后面参考了这位大佬的写法L2-001 紧急救援 (25 分)_mb61c049ad36458的技术博客_51CTO博客
发现还有一个最多救援队的约束。呜呜呜。
剩下的就很简单了,用一个结构体存点的编号、s到该点的最短距离、该点的救援队人数。后面始终没搞懂的一点就是为啥要按照距离从大到小的顺序进行比较,从小到大的顺序时,只能拿到2分。
Code Segment:
#include<cstdio>
#include<algorithm>
#include<queue>
#include<utility>
#include<vector>
#include<cstring>
using namespace std;
const int maxn=501;
int f[maxn],dis[maxn],a[maxn],vis[maxn],c[maxn],per[maxn];
vector<pair<int,int>> v[maxn];
struct node{
int first;
int second;
int w;
inline bool operator<(const node &x)const
{
if(second==x.second)
return w<x.w;
return second>x.second;
}
};
void spot(int d)
{
if(f[d]==d)
printf("%d",d);
else
{
spot(f[d]);
printf(" %d",d);
}
}
void dijk(int s,int d)
{
int g,h,i;
priority_queue<node> q;
memset(vis,0,sizeof(vis));
memset(c,0,sizeof(c));
memset(per,0,sizeof(per));
memset(dis,0x3f3f3f3f,sizeof(dis));
f[s]=s;
dis[s]=0;
c[s]=1;
per[s]=a[s];
q.push(node{s,0,a[s]});
while((!q.empty())&&(!vis[d]))
{
auto p=q.top();
q.pop();
g=p.first;
h=p.second;
if(vis[g])
continue;
vis[g]=1;
for(i=0;i<v[g].size();i++)
{
int e=v[g][i].first,b=v[g][i].second;
if(dis[e]>dis[g]+b)
{
f[e]=g;
dis[e]=dis[g]+b;
c[e]=c[g];
per[e]=per[g]+a[e];
q.push(node{e,dis[e],a[e]});
}
else if(dis[e]==dis[g]+b)
{
if(per[e]<per[g]+a[e])
{
f[e]=g;
per[e]=per[g]+a[e];
q.push(node{e,dis[e],a[e]});
}
c[e]+=c[g];
}
}
}
printf("%d %d\n",c[d],per[d]);
spot(d);
}
int main()
{
int n,m,s,d,l1,l2,l,i;
scanf("%d%d%d%d",&n,&m,&s,&d);
for(i=0;i<n;i++)
scanf("%d",&a[i]);
while(m--)
{
scanf("%d%d%d",&l1,&l2,&l);
v[l1].emplace_back(make_pair(l2,l));
v[l2].emplace_back(make_pair(l1,l));
}
dijk(s,d);
printf("\n");
}