http://poj.org/problem?id=3463
大致题意:给出一个有向图,从起点到终点求出最短路和次短路的条数之和。
解法:
用到的数组:dis[i][0]:i到起点的最短路,dis[i][1]:i到起点的严格次短路
vis[i][0],vis[i][1]:同一维的vis数组,标记距离是否已确定
sum[i][0]:i到起点的最短路条数,sum[i][1]:i到起点的次短路条数
同一维dijkstra,内循环先找出最短的距离(次短路或最短路)d,然后枚举与该点相连的点:
if(d < 最小) 更新最小和次小,包括距离以及路径条数
else if(d == 最小) 更新最短路径条数
else if(d < 次小) 更新次小,包括次小距离路径条数
else if(d == 次小) 更新次小路径条数
同一维不同的是外层循环次数为2*n-1次,因为更新最小n-1次,更新次小n次。
邻接表建图
#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <set>
#include <map>
#include <vector>
#include <math.h>
#include <string.h>
#include <queue>
#include <string>
#define LL long long
#define _LL __int64
using namespace std;
const int INF = 1<<28;
const int maxn = 1010;
const int maxm = 10010;
int cnt,head[maxn];
struct node
{
int v,w,next;
}edge[maxm];
int n,m;
int s,t;
int dis[maxn][2];
int vis[maxn][2];
int sum[maxn][2];
void init()
{
memset(head,-1,sizeof(head));
cnt = 0;
}
void add(int u, int v, int w)
{
edge[cnt] = (struct node){v,w,head[u]};
head[u] = cnt++;
}
void dijkstra()
{
for(int i = 1; i <= n; i++)
{
dis[i][0] = INF;
dis[i][1] = INF;
}
memset(vis,0,sizeof(vis));
memset(sum,0,sizeof(sum));
dis[s][0] = 0;
sum[s][0] = 1;
for(int i = 1; i <= 2*n-1; i++)
{
int Min = INF,pos = -1,flag;
for(int j = 1; j <= n; j++)
{
if(!vis[j][0] && Min > dis[j][0])
{
Min = dis[j][0];
pos = j;
flag = 0;
}
else if(!vis[j][1] && Min > dis[j][1])
{
Min = dis[j][1];
pos = j;
flag = 1;
}
}
if(pos == -1)
break;
vis[pos][flag] = 1;
for(int j = head[pos]; j != -1; j = edge[j].next)
{
int v = edge[j].v;
int w = edge[j].w;
if(dis[v][0] > dis[pos][flag] + w) //比最小要小
{
dis[v][1] = dis[v][0];
sum[v][1] = sum[v][0];
dis[v][0] = dis[pos][flag] + w;
sum[v][0] = sum[pos][flag];
}
else if(dis[v][0] == dis[pos][flag] + w) //等于最小
{
sum[v][0] += sum[pos][flag];
}
else if(dis[v][1] > dis[pos][flag] + w) //比次小要小
{
dis[v][1] = dis[pos][flag] + w;
sum[v][1] = sum[pos][flag];
}
else if(dis[v][1] == dis[pos][flag] + w) //等于次小
{
sum[v][1] += sum[pos][flag];
}
}
}
if(dis[t][1] == dis[t][0] + 1)
sum[t][0] += sum[t][1];
printf("%d\n",sum[t][0]);
}
int main()
{
int test;
int u,v,w;
scanf("%d",&test);
while(test--)
{
init();
scanf("%d %d",&n,&m);
for(int i = 0; i < m; i++)
{
scanf("%d %d %d",&u,&v,&w);
add(u,v,w);
}
scanf("%d %d",&s,&t);
dijkstra();
}
return 0;
}