题目:
题目描述
Mr_he 是一个求变的人,所以每天从学校机房回到家都要走不同的路径,当然劳累一天然 后漫步 在新鲜的大路上,打望过往行人和车辆也是一件非常惬意的事。 那么现在已经知道,从 Mr_he 的学校到家有n 个交叉路口,把他们从1..n 编号,我们认 为编 号为1 的是学校,编号为2 的为家,有m 条双向大路把这些路口连接起来。 Mr_he 打算每天沿着一条不同的路径回家(如果两条路径有一条道路不同,那么我们认为 这两条 路径是不同的),欣赏不同的风景。但他不想太晚回家,因此他不打算走“回头路”。换句话 说,他只 沿着满足如下条件的道路(A,B)走:存在一条从B 出发回家的路径比所有从A 出发回家的 路径都短。 那么你的任务是帮助 Mr_he 计算一共有多少条不同的回家路径。
输入输出格式
输入格式:
输入文件名为peek.in。 第一行为n,m,交叉点的数目和道路的数目。 以下 m 行每行 3 个整数:a,b,d(1≤a,b≤n,1≤d≤1000000),表示有一条连接 a 和 b 的双向道路,长度为 d。
输出格式:
输出路径条数。这个数可能很大,请输出 mod 20080814 的结果。
输入输出样例
输入样例#1:
5 6
1 3 2
1 4 2
3 4 3
1 5 12
4 2 34
5 2 24
输出样例#1:
2
说明
20%的数据:1<n≤10
50%的数据:1<n≤100
100%的数据:1<n≤1000,n-1≤m≤100000
思路:写个最短路,跑个记忆化搜索。
代码:
#include<bits/stdc++.h>
using namespace std;
#define maxn 1000
#define inf ((int)(1e9))
#define read(x) scanf("%d",&x)
#define md 20080814
struct Edge{
int x,y,z;
Edge(){}
Edge(int xx,int yy,int zz) {
x=xx,y=yy,z=zz;
}
};
struct Node {
int x,w;
Node(){}
Node(int xx,int ww) {
x=xx,w=ww;
}
bool operator < (const Node& oth) const {
return w>oth.w;
}
};
int n,m;
vector<Edge> a[maxn+5];
priority_queue<Node> que;
int dist[maxn+5];
bool vis[maxn+5];
vector<int> g[maxn+5];
void dijkstra() {
for(int i=1;i<=n;i++) dist[i]=inf;
dist[2]=0;
que.push(Node(2,0));
while(!que.empty()) {
int h=que.top().x;
que.pop();
if(vis[h]) continue;
vis[h]=true;
for(int i=0;i<a[h].size();i++) {
int y=a[h][i].y,z=a[h][i].z;
if(dist[y]>dist[h]+z) {
dist[y]=dist[h]+z;
que.push(Node(y,dist[y]));
}
}
}
}
int f[maxn+5];
int dfs(int x) {
if(g[x].size()==0) f[x]=1;
for(int i=0;i<g[x].size();i++) {
int y=g[x][i];
if(!f[y]) dfs(y);
f[x]=((long long)f[x]+(long long)f[y])%md;
}
}
int main() {
read(n),read(m);
for(int i=1;i<=m;i++) {
int x,y,z;
read(x),read(y),read(z);
a[x].push_back(Edge(x,y,z));
a[y].push_back(Edge(y,x,z));
}
dijkstra();
for(int i=1;i<=n;i++) {
for(int j=0;j<a[i].size();j++) {
int k=a[i][j].y;
if(dist[i]>dist[k]) g[i].push_back(k);
}
}
dfs(1);
printf("%d",f[1]);
return 0;
}