题目大意:
给你m条边与n个点
终点是点2,起点是点1
当(A,B)中A到终点的最短路径大于B到终点的最短路径的时候你才可以走这两个点
问你有多少条路径可以从起点走到终点
思路:
就是从终点向其他所有点延伸
找2到其他所有点的最短路径
这样就形成了一个最短路径树
我们设一个数组表示每个点能走到起点的路径种类
(方便记忆化搜素)
把起点的值设为1
然后从点2开始按题目给的要求我们向上倒着走
最后把数组中点2的值给他加上就好了
AC代码:
#include <bits/stdc++.h>
using namespace std;
vector<pair<int,int>>e[1010];
int d[1010];
int path[1010];
void dij(int st)
{
priority_queue<pair<int,int>,vector<pair<int,int>>,greater<pair<int,int>>>q;//小顶堆
memset(d,0x3f3f,sizeof(d));
int vis[1010]= {0};
q.push({0,st});
d[st]=0;
while(!q.empty())
{
int x=q.top().second;//这里跟vector不一样是second因为这里用小顶堆优先看前面的边长
q.pop();
if(vis[x])continue;
vis[x]=1;
for(int i=0; i<e[x].size(); i++)
{
int y=e[x][i].first;
int w=e[x][i].second;
if(d[y]>d[x]+w)
{
d[y]=d[x]+w;
q.push({d[y],y});
}
}
}
return;
}
int dfs(int x)
{
if(path[x]!=-1)return path[x];//记忆化搜素
path[x]=0;
for(int i=0; i<e[x].size(); i++)
{
int y=e[x][i].first;
if(d[x]<d[y])
{
path[x]+=dfs(y);//往上找起点
}
}
return path[x];
}
int main()
{
int n,m;
while(cin>>n)
{
if(n==0)break;
cin>>m;
memset(path,-1,sizeof(path));
path[1]=1;
for(int i=1; i<=n; i++)e[i].clear();
for(int i=0; i<m; i++)
{
int a,b,w;
cin>>a>>b>>w;
e[a].push_back(make_pair(b,w));
e[b].push_back(make_pair(a,w));
}
dij(2);
int ans=dfs(2);
cout<<ans<<endl;
}
return 0;
}