Problem Description
Do not sincere non-interference。
Like that show, now starvae also take part in a show, but it take place between city A and B. Starvae is in city A and girls are in city B. Every time starvae can get to city B and make a data with a girl he likes. But there are two problems with it, one is starvae must get to B within least time, it's said that he must take a shortest path. Other is no road can be taken more than once. While the city starvae passed away can been taken more than once.
So, under a good RP, starvae may have many chances to get to city B. But he don't know how many chances at most he can make a data with the girl he likes . Could you help starvae?
Input
The first line is an integer T indicating the case number.(1<=T<=65)
For each case,there are two integer n and m in the first line ( 2<=n<=1000, 0<=m<=100000 ) ,n is the number of the city and m is the number of the roads.
Then follows m line ,each line have three integers a,b,c,(1<=a,b<=n,0<c<=1000)it means there is a road from a to b and it's distance is c, while there may have no road from b to a. There may have a road from a to a,but you can ignore it. If there are two roads from a to b, they are different.
At last is a line with two integer A and B(1<=A,B<=N,A!=B), means the number of city A and city B.
There may be some blank line between each case.
Output
Output a line with a integer, means the chances starvae can get at most.
Sample Input
3 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 1 1
题目大意 : 输入一个有向图, 输出从起点到终点的最短路有多少条, 每条边只允许走一次
思路 : 首先跑一遍最短路, 将从起点到各个点之间的最短路给保存下来, 再跑一遍最短路, 并将所有 “可能构成最短路的边” 给存到新图中, 判定条件为:dis【v】== 已保存下来的最短路的值, 不清楚的可以自己画画图。 因为走过的边不能再走, 可以想到网络流就有这样的特点, 所以存新图的时候将权值置为1即可, 最后跑一遍最大流, 答案就出来了。
Accepted code
#include<bits/stdc++.h>
using namespace std;
#define sc scanf
#define mem memset
#define Min(a, b) a = min(a, b)
#define Max(a, b) a = max(a, b)
typedef long long ll;
const int MAXN = 1e5 + 10;
const int INF = 0x3f3f3f3f;
struct Edge
{
int v, w, next;
}e[MAXN << 1], edge[MAXN << 1]; // e为最短路边, edge为最大流边
struct node
{
int id, w;
bool operator < (const node &oth) const
{
return w > oth.w;
}
}mid;
int head[MAXN], pre[MAXN], cur[MAXN], n, m, cnt, T; // head和pre分别为链式前向星
int dis[MAXN], dist[MAXN], dep[MAXN], sp, tp, tot; // dist为保存的最短路
void init() {
mem(e, 0, sizeof(e));
mem(pre, -1, sizeof(pre));
mem(head, -1, sizeof(head));
cnt = tot = 0;
}
void add(int from, int to, int dis) { // 最短路存边
e[++cnt].v = to;
e[cnt].w = dis;
e[cnt].next = head[from];
head[from] = cnt;
}
void Add(int from, int to, int wi) { // 网络流存边
edge[tot].v = to; edge[tot].next = pre[from];
edge[tot].w = wi; pre[from] = tot++;
edge[tot].v = from; edge[tot].next = pre[to];
edge[tot].w = 0; pre[to] = tot++;
}
void dijkstra(int u) { // 第一次最短路用来保存最短路径
priority_queue <node> q;
mem(dis, INF, sizeof(dis));
dis[u] = 0;
q.push({ u, 0 });
mem(pre, -1, sizeof(pre));
pre[u] = -1;
while (!q.empty()) {
mid = q.top();
q.pop();
int ans = mid.id;
if (mid.w != dis[ans]) continue;
for (int i = head[ans]; i != -1; i = e[i].next) {
if (dis[e[i].v] > dis[ans] + e[i].w) {
dis[e[i].v] = dis[ans] + e[i].w;
q.push({ e[i].v, dis[e[i].v] });
}
}
}
}
void dij(int u) { // 第二遍最短路用来保存可以到终点路程最短的路径
priority_queue <node> q;
mem(dis, INF, sizeof(dis));
dis[u] = 0;
q.push({ u, 0 });
mem(pre, -1, sizeof(pre));
pre[u] = -1;
while (!q.empty()) {
mid = q.top();
q.pop();
int ans = mid.id;
if (mid.w != dis[ans]) continue;
for (int i = head[ans]; i != -1; i = e[i].next) { // 路径相同则存图
if (dist[e[i].v] == dis[ans] + e[i].w) Add(ans, e[i].v, 1);
if (dis[e[i].v] > dis[ans] + e[i].w) {
dis[e[i].v] = dis[ans] + e[i].w;
q.push({ e[i].v, dis[e[i].v] });
}
}
}
}
bool bfs() { // 寻找增广路
queue <int> q;
mem(dep, 0, sizeof(dep));
dep[sp] = 1, q.push(sp);
while (!q.empty()) {
int now = q.front();
q.pop();
for (int i = pre[now]; i != -1; i = edge[i].next) {
int vi = edge[i].v;
if (!dep[vi] && edge[i].w) {
dep[vi] = dep[now] + 1;
q.push(vi);
}
}
}
if (dep[tp]) return true;
return false;
}
int dfs(int x, int d) { // 找流量
if (x == tp || d == 0) return d;
int res = 0, r;
for (int &i = cur[x]; i != -1; i = edge[i].next) {
int vi = edge[i].v;
if (dep[vi] == dep[x] + 1 && edge[i].w) {
r = dfs(vi, min(edge[i].w, d - res));
if (r > 0) {
edge[i].w -= r;
edge[i ^ 1].w += r;
res += r;
}
}
}
if (!res) dep[x] = 0;
return res;
}
int dinic() {
int flow = 0, ans;
while (bfs()) {
for (int i = 1; i <= n; i++) cur[i] = pre[i];
flow += dfs(sp, INF);
}
return flow;
}
int main()
{
cin >> T;
while (T--) {
sc("%d %d", &n, &m);
init();
for (int i = 0; i < m; i++) {
int ui, vi, wi;
sc("%d %d %d", &ui, &vi, &wi);
add(ui, vi, wi);
}
sc("%d %d", &sp, &tp);
dijkstra(sp);
for (int i = 1; i <= n; i++) dist[i] = dis[i]; // 备注最短路
dij(sp);
cout << dinic() << endl;
}
return 0;
}