题目链接: http://poj.org/problem?id=3463
题意:给定一张有向图,以及起点 s 终点 f, 求从 s 到 f 的最短路的路径条数 以及 比最短路径大1 的路径条数 之和
思路: 用A*算法,类似求第K短路 来写 超时。就只能求最短路 与 次最短路的路径长度以及 它们各自的条数。
求次最短路类似于求次最大值。
AC代码:
#include<cstdio>
#include<queue>
#include<cstring>
#include<vector>
using namespace std;
const int maxn = 1010;
vector<pair<int,int> >E[maxn];
int d[maxn][2]; ///d[i][0] 表示最短 d[i][1] 表示次最短
int cnt[maxn][2]; ///cnt[i][0] 表示最短的条数, cnt[i][1] 表示 次最短的条数
int vis[maxn][2];
struct node{
int v;
int flag;
node(){}
node(int v,int flag):v(v),flag(flag){}
friend bool operator < (const node &A,const node &B){
return d[A.v][A.flag] > d[B.v][B.flag];
}
};
void init(){
for(int i = 0;i < maxn;i ++){
E[i].clear();
d[i][0] = d[i][1] = 1e9;
cnt[i][0] = cnt[i][1] = 0;
vis[i][0] = vis[i][1] = 0;
}
}
int dijsktra(int s,int f){
d[s][0] = 0;
cnt[s][0] = 1;
priority_queue<node>Q;
Q.push(node(s,0));
while(!Q.empty()){
int v = Q.top().v;
int flag = Q.top().flag;
Q.pop();
if(vis[v][flag]) continue; ///因为要多次Q.push() , 可能会放入重复的点
vis[v][flag] = 1;
for(int i = 0;i < E[v].size();i ++){
int to = E[v][i].first;
int dis = d[v][flag] + E[v][i].second;
if(d[to][0] > dis){
if(d[to][0] != 1e9){
d[to][1] = d[to][0];
cnt[to][1] = cnt[to][0];
Q.push(node(to,1));
}
d[to][0] = dis;
cnt[to][0] = cnt[v][flag];
Q.push(node(to,0));
}
else if(d[to][0] == dis){
cnt[to][0] += cnt[v][flag];
}
else if(d[to][1] > dis){
d[to][1] = dis;
cnt[to][1] = cnt[v][flag];
Q.push(node(to,1));
}
else if(d[to][1] == dis){
cnt[to][1] += cnt[v][flag];
}
}
}
if(d[f][0] + 1 == d[f][1])
return cnt[f][0] + cnt[f][1];
return cnt[f][0];
}
int main()
{
int t; scanf("%d",&t);
while(t--){
init();
int n ,m; scanf("%d%d",&n,&m);
int A,B,L;
for(int i = 0;i < m;i ++){
scanf("%d%d%d",&A,&B,&L);
E[A].push_back(make_pair(B,L));
}
int s,f; scanf("%d%d",&s,&f);
printf("%d\n",dijsktra(s,f));
}
return 0;
}