题目链接在这里
题目描述
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
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
题目大意是给出n个点m条边,让一个人从A点走到B点,每次都要走最短路,且每条最短路的边不能重复,问有多少条这样的路。
首先算出来A点到每点的最短路dis1,然后再算出来B点到每点的最短路dis2,然后遍历每一条边,如果dis1[edge.u] + dis2[edge.v] + edge.w == dis1[B],那么就把这条边加入到最大流的计算边中去。然后通过sap算法计算从A点到B点的最大流。
第一次写最大流题。。。。看了好半天
AC代码:
#include
#include
#include
#include
#include
#include
using namespace std;
const int MaxN = 100010;
const int MaxM = 5e5 + 10;
const int INF = 0x3f3f3f3f;
struct EdgeFlow{
int v, flow, cap, nxt;
}edge_flow[MaxM];
struct Edge{
int v, w;
};
vector G[MaxN];
int dis[MaxN], dis1[MaxN], dis2[MaxN];
int tol, par[MaxN];
int cur[MaxN], gap[MaxN], dep[MaxN], pre[MaxN];
int a[MaxN], b[MaxN], c[MaxN];
int n, m;
inline void addEdge1(int u, int v, int w){
G[u].push_back(Edge{v, w});
}
void addEdge2(int u, int v, int w, int rw = 0){
edge_flow[tol].v = v;
edge_flow[tol].cap = w;
edge_flow[tol].flow = 0;
edge_flow[tol].nxt = par[u];
par[u] = tol++;
edge_flow[tol].v = u;
edge_flow[tol].cap = rw;
edge_flow[tol].flow = 0;
edge_flow[tol].nxt = par[v];
par[v] = tol++;
}
void dijkstra(int st){
memset(dis, INF, sizeof(dis));
priority_queue, vector >, greater > > que;
dis[st] = 0;
que.push(make_pair(0, st));
while(!que.empty()){
pair p = que.top();
que.pop();
int u = p.second;
for(int i = 0; i < G[u].size(); ++i){
Edge e = G[u][i];
int v = e.v;
if(dis[v] > dis[u] + e.w){
dis[v] = dis[u] + e.w;
que.push(make_pair(dis[v], v));
}
}
}
}
int sap(int st, int ed){
int N = n;
memset(gap, 0, sizeof(gap));
memset(dep, 0, sizeof(dep));
memset(cur, 0, sizeof(cur));
int u = st;
pre[u] = -1;
gap[0] = N;
int ans = 0;
while(dep[st] < N){
if(u == ed){
int Min = INF;
for(int i = pre[u]; i != -1; i = pre[edge_flow[i ^ 1].v])
if(Min > edge_flow[i].cap - edge_flow[i].flow)
Min = edge_flow[i].cap - edge_flow[i].flow;
for(int i = pre[u]; i != -1; i = pre[edge_flow[i ^ 1].v]){
edge_flow[i].flow += Min;
edge_flow[i ^ 1].flow -= Min;
}
u = st;
ans += Min;
continue;
}
bool flag = false;
int v;
for(int i = cur[u]; i != -1; i = edge_flow[i].nxt){
v = edge_flow[i].v;
if(edge_flow[i].cap - edge_flow[i].flow && dep[v] + 1 == dep[u]){
flag = true;
cur[u] = pre[v] = i;
break;
}
}
if(flag){
u = v;
continue;
}
int Min = N;
for(int i = par[u]; i != -1; i = edge_flow[i].nxt){
if(edge_flow[i].cap - edge_flow[i].flow && dep[edge_flow[i].v] < Min){
Min = dep[edge_flow[i].v];
cur[u] = i;
}
}
gap[dep[u]]--;
if(!gap[dep[u]]) return ans;
dep[u] = Min + 1;
gap[dep[u]]++;
if(u != st)
u =edge_flow[pre[u] ^ 1].v;
}
return ans;
}
int main(){
int T;
scanf("%d", &T);
while(T--){
scanf("%d %d", &n, &m);
for(int i = 0; i <= n; ++i)
G[i].clear();
for(int i = 0; i < m; ++i){
scanf("%d%d%d", &a[i], &b[i], &c[i]);
addEdge1(a[i], b[i], c[i]);
}
int st, ed;
scanf("%d%d", &st, &ed);
dijkstra(st);
memcpy(dis1, dis, sizeof(dis));
for(int i = 0; i <= n; ++i)
G[i].clear();
for(int i = 0; i < m; ++i)
addEdge1(b[i], a[i], c[i]);
dijkstra(ed);
memcpy(dis2, dis, sizeof(dis));
tol = 0;
memset(par, -1, sizeof(par));
for(int i = 0; i < m; ++i){
if(a[i] != b[i] && dis1[a[i]] + dis2[b[i]] + c[i] == dis1[ed])
addEdge2(a[i], b[i], 1);
}
printf("%d\n", sap(st, ed));
}
return 0;
}