\quad 这是一个最短路的题,但要求多了一些,要求我们统计最短路条数,若有多条最短路,需要输出能获得营救队伍最多的值。故需要我们在最忧子结构里面更新两个变量。我用num[v]表示起点s到点v最短路径的条数,res[v]表示起点s到v点所能得到的最多队伍数,故在初始化时候num[s]=1,res[s]=a[s],a[s]表示s点营救队伍数量。最优子结构如下:
if(dis[v]>dis[u]+w)
{
dis[v] = dis[u]+w;
num[v] = num[u];
res[v] = res[u]+a[v];
}
else if(dis[v]==dis[u]+w)
{
num[v] += num[u];
res[v] = max(res[v], res[u]+a[v]);
}
\quad 总程序如下:
#include
#include
#include
#include
using namespace std;
const int maxn = 501;
int a[maxn]; // 记录每个点营救队伍数目
vector<pair<int, int> > E[maxn];
int vis[maxn], dis[maxn];
int num[maxn], res[maxn];
void dijstra(int s, int t)
{
fill(dis, dis+maxn, 0x3f3f3f3f);
dis[s] = 0;
num[s] = 1;
res[s] = a[s];
priority_queue<pair<int, int> > q;
q.push(make_pair(0, s));
while(!q.empty())
{
int u = q.top().second;
q.pop();
if(vis[u]==1) continue;
vis[u] = 1;
for (int i = 0; i < E[u].size(); ++i)
{
int v = E[u][i].first, w = E[u][i].second;
if(dis[v]>dis[u]+w)
{
dis[v] = dis[u]+w;
num[v] = num[u];
res[v] = res[u]+a[v];
if(vis[v]==0) q.push(make_pair(-dis[v], v));
}
else if(dis[v]==dis[u]+w)
{
num[v] += num[u];
res[v] = max(res[v], res[u]+a[v]);
if(vis[v]==0) q.push(make_pair(-dis[v], v));
}
}
}
cout << num[t] << " " << res[t];
}
int main(int argc, char const *argv[])
{
int N, M, s, t;
cin >> N >> M >> s >> t;
for(int i = 0; i < N; i++) cin >> a[i];
while(M--)
{
int u, v, w;
cin >> u >> v >> w;
E[u].push_back(make_pair(v, w));
E[v].push_back(make_pair(u, w));
}
dijstra(s, t);
return 0;
}
\quad 这里也给出用spfa求解的程序,需注意的是spfa可能会重复访问一个点,因此在统计最短路径条数的时候需要额外用一个set进行存储和去重的工作。
#include
#include
#include
#include
#include
using namespace std;
const int maxn = 1001;
vector<pair<int, int> > E[maxn];
int teams[maxn];
int pathNum[maxn], teamNum[maxn];
int inq[maxn], dis[maxn];
set<int> st[maxn];
void spfa(int s, int t)
{
fill(dis, dis+maxn, 0x3f3f3f3f);
dis[s] = 0;
queue<int> q;
q.push(s);
inq[s] = 1;
pathNum[s] = 1;
teamNum[s] = teams[s];
while(!q.empty())
{
int u = q.front();
q.pop();
inq[u] = 0;
for (int i = 0; i < E[u].size(); ++i)
{
int v = E[u][i].first, w = E[u][i].second;
if(dis[v]>dis[u]+w)
{
dis[v] = dis[u]+w;
pathNum[v] = pathNum[u];
teamNum[v] = teamNum[u]+teams[v];
st[v].clear();
st[v].insert(u);
if(inq[v]==0) q.push(v), inq[v]=1;
}
else if(dis[v]==dis[u]+w)
{
st[v].insert(u);
pathNum[v] = 0; // //因为spfa会重复到一个点 所以可能重复的边
for(set<int>::iterator it=st[v].begin(); it!=st[v].end(); it++) pathNum[v] += pathNum[*it];
teamNum[v] = max(teamNum[v], teamNum[u]+teams[v]);
if(inq[v]==0) q.push(v), inq[v]=1;
}
}
}
cout << pathNum[t] << " " << teamNum[t];
}
int main(int argc, char const *argv[])
{
int N, M, s, t;
cin >> N >> M >> s >> t;
for(int i = 0; i < N; i++) cin >> teams[i];
while(M--)
{
int u, v, w;
cin >> u >> v >> w;
E[u].push_back(make_pair(v, w));
E[v].push_back(make_pair(u, w));
}
spfa(s, t);
return 0;
}