题意
起点为1,终点为2,Bob想从起点走到终点,但是他只会走这样的路,设dis[i]
: i点到终点的最短路径,对于边(u,v),如果dis[u]>dis[v],那么Bob就可以走这条边。现在问Bob有多少种方法从起点走到终点。
题解
先以终点为开始求一遍最短路,这样只要dis[A] < dis[B] 那就连一条B到A的边,整张图就是一个DAG图,从起点开始动态规划求到终点的方案数即可。
代码
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1000+5;
const int INF = 0x3f3f3f3f;
#define to second
#define co first
typedef pair<int,int> pii;
int S,E,n,m;
vector<pii> G[maxn];
int cnt[maxn], d[maxn];
void add(int u,int v,int w) {
G[u].push_back(pii(w,v));
}
void init() {
for(int i = 0; i <= n; ++i)
G[i].clear();
}
void solve() {
memset(d,INF,sizeof d);
// memset(cnt,0,sizeof cnt);
d[S] = 0;
// cnt[S] = 1;
priority_queue<pii> que;
que.push(pii(d[S], S));
while(!que.empty()) {
pii u = que.top();
que.pop();
if(d[u.second] < u.first)
continue;
int x = u.second;
// cout << x << endl;
for(int i = 0; i < G[x].size(); ++i) {
pii &e = G[x][i];
// cout << e.to << endl;
if(d[e.to] > d[x]+e.co) {
d[e.to] = d[x]+e.co;
// cnt[e.to] = cnt[x];
que.push(pii(d[e.to],e.to));
}
}
}
}
int ans[maxn];
int dp(int x) {
if(x == 1)
return 1;
if(ans[x] != -1)
return ans[x];
ans[x] = 0;
for(int i = 0; i < G[x].size(); ++i) {
pii &e = G[x][i];
if(d[e.to] > d[x])
ans[x] += dp(e.to);
}
return ans[x];
}
int main() {
// freopen("in.txt","r",stdin);
while(scanf("%d%d", &n, &m) && n) {
memset(ans, -1,sizeof ans);
S = 2; E = 1;
int u,v,w;
init();
for(int i = 0; i < m; ++i) {
scanf("%d%d%d", &u, &v, &w);
add(u,v,w);
add(v,u,w);
}
solve();
printf("%d\n", dp(2));
}
return 0;
}