题意:

一个人从公司回家,他可以从A走到B如果从存在从B出发到家的一条路径的长度小于任何一条从A出发到家的路径的长度。

问这样的路径有多少条。

思路:

题意并不好理解,存在从B出发到家的一条路径的长度小于任何一条从A出发到家的路径的长度,从这个条件可以推出只要满足B到家的最短路小于从A到家的最短路,那么就是满足条件的。

所以从家开始求到各个点的最短路,然后从公司开始进行记忆化搜索求出路径的总条数。

如果两个点A和B满足d[A] > d[B],那么A到家的路径条数一定包括B到家的路径条数,临界条件就是到家了,那么只有一条路可以走。

复杂度O(nlog(n));

代码:

 #include <stdio.h>
#include <vector>
#include <queue>
#include <string.h>
using namespace std; struct edge
{
int to;
long long cost; edge(int uu,long long vv)
{
to = uu;
cost = vv;
}
}; const int maxn = ; vector<edge> g[maxn];
long long d[maxn];
bool vis[maxn];
long long dp[maxn]; void adde(int st,int to,int cost)
{
g[st].push_back(edge(to,cost));
} void dij(int s,int n)
{
for (int i = ;i <= n;i++) d[i] = ;
memset(vis,,sizeof(vis)); d[s] = ; for (int i = ;i < n - ;i++)
{
long long dis = ;
int x; for (int j = ;j <= n;j++)
{
if (d[j] <= dis && !vis[j])
{
dis = d[j];
x = j;
}
} vis[x] = ; for (int j = ;j < g[x].size();j++)
{
edge e = g[x][j]; if (d[e.to] > d[x] + e.cost)
{
//ways[e.to] = ways[x];
d[e.to] = d[x] + e.cost;
}
}
}
} int dfs(int u,int fa)
{
if (dp[u] != -) return dp[u]; dp[u] = ; for (int i = ;i < g[u].size();i++)
{
int v = g[u][i].to; if (v == fa) continue; if (d[u] > d[v])
{
if (dp[v] != -) dp[u] += dp[v];
else dp[u] += dfs(v,u);
}
} return dp[u];
} int main()
{
int n,m; while (scanf("%d",&n) != EOF)
{
if (n == ) break; scanf("%d",&m); for (int i = ;i <= n;i++) g[i].clear();
memset(dp,-,sizeof(dp)); //memset(ways,0,sizeof(ways)); for (int i = ;i < m;i++)
{
int x,y,z; scanf("%d%d%d",&x,&y,&z); adde(x,y,z);
adde(y,x,z);
} dij(,n); //memset(vis,0,sizeof(vis)); dp[] = ; dfs(,-); printf("%lld\n",dp[]);
} return ;
}
05-02 11:17