UESTC 1053 Shortest road
//题目类型;最短路-求最短路的条数
//解题思路:类似于贪心的思路,基本方法为采用递推,用 p[] 记录路径条数,
//(1)dist[u]+ w(u,v)== dist[v] ,则 p[v]+= p[u]
//(2)dist[u]+ w(u,v)< dist[v] 则 p[v]= p[u]。
//由于本题边数较多,所以采用邻接表的结构存储
#include <iostream>
#include <algorithm>
#include <queue>
#include <cstdio>
//#include <conio.h>
using namespace std;
const int MAXN = 1001; //点数
const int marray = 1000001;
const int INF=0x7fffffff;
struct edge_T {
int v;
int w;
edge_T *next;
}*adj[MAXN], edges[2*marray];
struct node_T {
int v;
int len;
bool operator < (const node_T &nod) const {
return len > nod.len;
}
};
int edgenum; //记录边的总数
int vn,en; //记录定点数和边数
int path[MAXN];
int dist[MAXN];
int src,des;
void addEdge(int u, int v, int w) {
edge_T *ptr = &edges[edgenum ++];
ptr -> v = v;
ptr -> w = w;
ptr -> next = adj[u]; //往前插入边
adj[u] = ptr;
}
void dijkstra(int s) { //n代表结点总数
priority_queue <node_T> Q; //使用优先级队列实现
node_T cur;
cur.v = s;
cur.len = 0;
Q.push(cur);
for(int i = 1; i <= vn; i ++)
{
dist[i] = INF;
path[i] = 0;
}
dist[s] = 0;
path[s] = 1;
while(! Q.empty()) {
int v = Q.top().v; //优先级队列使用top()
int len = Q.top().len;
Q.pop();
if(dist[v]!=len) continue;
for(edge_T *ptr = adj[v]; ptr; ptr = ptr -> next) {
int u = ptr -> v;
int w = ptr -> w;
if(dist[v] + w < dist[u]) {
dist[u] = dist[v] + w;
cur.v = u;
cur.len = dist[u];
Q.push(cur);
path[u] = path[v]; //此处是关键
}
else if(dist[v]+w==dist[u])
{
path[u] += path[v]; //此处是关键
}
}
}
}
int main() {
//freopen("1.txt","r",stdin);
int t;
int i;
int src;
scanf("%d",&t);
while(t--)
{
scanf("%d %d", &vn, &en);
for(i = 1; i <= vn; i ++)
{
adj[i] = NULL; //初始化邻接表的指针
}
edgenum = 0; //初始化边数
int u, v;
int w;
for(i = 1; i <= en; i ++)
{
scanf("%d%d%d", &u, &v, &w); //最好采用此种读取方式,下边一种在某些题目中会出错
addEdge(u, v, w);
addEdge(v, u, w);
}
scanf("%d%d",&src,&des);
dijkstra(src);
if(dist[des]==INF) printf("0\n0\n\n");
else printf("%d\n%d\n\n",dist[des],path[des]);
}
//getch();
return 0;
}
浙公网安备 33010602011771号