UVa 10917 林中漫步

时间:2023-03-09 18:10:30
UVa 10917 林中漫步

https://vjudge.net/problem/UVA-10917

题意:

给出一个图,求出从1走到2共有多少种走法。前提是他只沿着满足如下条件的道路(A,B)走:存在一条从B出发回家的路径,比所有从A出发回家的路径都短。

思路:

首先用Dijkstra算法求出每个点到家的最短路径,那么题目的要求也就变成了d[B]<d[A],这样,我们创建了一个新的图,当且仅当d[B]<d[A]时加入有向边A->B,这样就是一个DAG,直接用动态规划计数。

 #include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>
using namespace std; const int maxn = + ;
const int INF = 0x3f3f3f3f; int n, m; struct Edge
{
int from, to, dist;
Edge(int u, int v, int d) :from(u), to(v), dist(d){}
}; struct HeapNode
{
int d, u;
HeapNode(int x, int y) :d(x), u(y){}
bool operator < (const HeapNode& rhs) const
{
return d>rhs.d;
}
}; struct Dijkstra
{
int n, m;
vector<Edge> edges;
vector<int> G[maxn];
bool done[maxn];
int d[maxn];
int p[maxn];
int dp[maxn]; void init(int n)
{
this->n = n;
for (int i = ; i < n; i++)
G[i].clear();
edges.clear();
} void AddEdge(int from, int to, int dist)
{
edges.push_back(Edge(from, to, dist));
int m = edges.size();
G[from].push_back(m - );
} void dijkstra(int s)
{
priority_queue<HeapNode> Q;
for (int i = ; i < n; i++) d[i] = INF;
memset(done, , sizeof(done));
d[s] = ;
Q.push(HeapNode(, s));
while (!Q.empty())
{
HeapNode x = Q.top();
Q.pop();
int u = x.u;
if (done[u]) continue;
done[u] = true;
for (int i = ; i < G[u].size(); i++)
{
Edge& e = edges[G[u][i]];
if (d[e.to]>d[u] + e.dist)
{
d[e.to] = d[u] + e.dist;
p[e.to] = e.from;
Q.push(HeapNode(d[e.to], e.to));
}
}
}
} int DP(int s)
{
if (s == ) return ;
if (dp[s] != -) return dp[s];
dp[s] = ;
for (int i = ; i < G[s].size(); i++)
{
Edge e = edges[G[s][i]];
if (d[e.to] < d[s]) dp[s] += DP(e.to);
}
return dp[s];
}
}t; int main()
{
//freopen("D:\\input.txt", "r", stdin);
int u, v, d;
while (~scanf("%d", &n) && n)
{
scanf("%d", &m);
t.init(n);
for (int i = ; i < m; i++)
{
scanf("%d%d%d", &u, &v, &d);
t.AddEdge(u - , v - , d);
t.AddEdge(v - , u - , d);
}
t.dijkstra();
memset(t.dp, -, sizeof(t.dp));
t.DP();
printf("%d\n", t.dp[]);
}
return ;
}