题意:每天下班后,某人都要从他的办公室,深林的一端,结点编号为1,走到深林的另一端,结点编号为2,为了放松心情,并且能尽快到家,他想知道有多少路满足条件的路能够到家。
条件:当前在A点,与A相连的B点如果满足,A到2的最短距离大于B到2的最短距离,那么A可以从B走,否则不能走。按照这样的规则走到终点,算一条路径,一开始也以为是求最短路的条数= =
思路:dijstra求最短路,然后记忆化搜索
网址:http://acm.hdu.edu.cn/showproblem.php?pid=1142
#include<cstdio>
#include<vector>
#include<queue>
#include<cstring>
using namespace std;
const int maxn = 1010;
const int INF = 1<<30;
vector<int> g[maxn];
vector<int> w[maxn];
int d[maxn],vis[maxn],dp[maxn];
int n,m;
struct node
{
int d,x;
bool operator < (const node &b)const
{
return d>b.d;
}
};
void dijstra(int s)
{
priority_queue<node,vector<node> > q;
for(int i=0;i<=n;i++)d[i]=INF;
d[s]=0;
q.push(node{0,s});
while(!q.empty())
{
node a = q.top();q.pop();
int x = a.x;
if(vis[x])continue;
vis[x]=1;
for(int i=0;i<g[x].size();i++)
{
int v=g[x][i];
if(d[v]>=a.d+w[x][i])
{
d[v]=a.d+w[x][i];
q.push(node{d[v],v});
}
}
}
}
int dfs(int u)
{
int sum=0;
if(dp[u]!=-1)return dp[u];
if(u==2)return 1;
for(int i=0;i<g[u].size();i++)
{
int v=g[u][i];
if(d[u]>d[v])
sum+=dfs(v);
}
return dp[u]=sum;
}
int main()
{
while(scanf("%d",&n)&&n)
{
scanf("%d",&m);
for(int i=1;i<=n;i++)
{
g[i].clear();
w[i].clear();
}
for(int i=1;i<=n;i++)dp[i]=-1;
memset(vis,0,sizeof(vis));
int u,v,ww;
for(int i=0;i<m;i++)
{
scanf("%d%d%d",&u,&v,&ww);
g[u].push_back(v);
w[u].push_back(ww);
g[v].push_back(u);
w[v].push_back(ww);
}
dijstra(2);
dfs(1);
printf("%d\n",dp[1]);
}
}