题目链接:http://acm.scu.edu.cn/soj/problem.action?id=4526
Time Limit:1000ms Memory Limit:32768K
Description
给定一个n个节点,m条有向边的图,再给你起点和终点,请问其中有多少条互不重叠的从起点到终点的最短路,即互相没有公共边的最短路个数(可以有公共点),用过边的不能再用。
Input
输入第一行有一个T,表示样例个数。(T≤60)
每个样例第一行有两个整数n,m(n≤1000,m≤100000)
然后是m行,代表每一条边的起点终点和权值。
然后是一个两个整数,代表起点和终点。
Output
输出最短路个数。
Sample Input
4
4 4
1 2 1
1 3 1
2 4 1
3 4 1
1 4
7 8
1 2 1
1 3 1
2 4 1
3 4 1
4 5 1
4 6 1
5 7 1
6 7 1
1 7
6 7
1 2 1
2 3 1
1 3 3
3 4 1
3 5 1
4 6 1
5 6 1
1 6
2 2
1 2 1
1 2 2
1 2
Sample Output
2
2
1
1
Problem solving:
最短路问题,使用邻接表的方法存边,再跑一遍Dijkstra算法(优先队列),最后搜索一下,把能到达终点的边找出来,只要用过的就不能用了。这里我没用STL里面的优先队列,我用的是数组型的队列,方便每次都让最短的边出队。
#include <queue>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define N 1010
using namespace std;
struct edgg {
int t, s;
}Q[N * N];
struct edge {
int u, v, w;
}e[100 * N];
struct edga {
int node[N], path[N], w[N], num;
}pre[N];
int cnt, f[N], vis[N], dis[N], vish[100 * N];
void Add(int u, int v, int w) {
e[++cnt] = (edge){f[u], v, w};
f[u] = cnt;
}
void Q_sort(struct edgg a[], int n, int min) {
int j = n - 1;
for (int i = 0; i < n; i++)
if (a[i].s < min)
j = i, min = a[i].s;
swap(a[0], a[j]);
}
void Dijkstra(int s) {
int t, v;
int head, tail;
memset(vis, 0, sizeof(vis));
memset(pre, 0, sizeof(pre));
memset(dis, 0x3f, sizeof(dis));
head = tail = dis[s] = 0;
Q[tail].t = s;
Q[tail++].s = 0;
while (head < tail) {
struct edgg t = Q[head++];
if (vis[t.t])
continue;
vis[t.t] = 1;
for (int i = f[t.t]; i; i = e[i].u) {
v = e[i].v;
if (dis[v] > t.s + e[i].w) {
dis[v] = t.s + e[i].w;
pre[v].num = 0;
pre[v].path[pre[v].num] = i;
pre[v].node[pre[v].num++] = t.t;
Q[tail].t = v;
Q[tail++].s = dis[v];
Q_sort(Q + head, tail - head, dis[v]);
}
else if (dis[v] == t.s + e[i].w) {
pre[v].path[pre[v].num] = i;
pre[v].node[pre[v].num++] = t.t;
}
}
}
}
void dfs(int v) {
int t;
for (int i = 0; i < pre[v].num; i++) {
t = pre[v].path[i];
if (vish[t])
continue;
vish[t] = 1;
dfs(pre[v].node[i]);
}
}
int main() {
int s, t, u, v, w, n, m, ans, test;
scanf("%d", &test);
while (test--) {
cnt = ans = 0;
scanf("%d%d", &n, &m);
memset(f, 0, sizeof(f));
for (int i = 0; i < m; i++) {
scanf("%d%d%d", &u, &v, &w);
Add(u, v, w);
}
scanf("%d%d", &s, &t);
memset(vish, 0, sizeof(vish));
Dijkstra(s);
dfs(t);
for (int i = f[s]; i; i = e[i].u)
if (vish[i])
ans++;
printf("%d\n", ans);
}
return 0;
}