题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3416
题意:在城市A的男孩想去跟城市B的女孩约合,不过他去城市B必须走A->B最短路,并且走过的路不可以再走,问他最多能看这个女孩多少次。
思路:首先找出这条最短路径:
先从A->B做一次spfa,然后再反向建图从 B->A做一次spfa。然后遍历原图每一条边e(u,v),若满足
disA[u] + disB[v] + w(u,v) == disA[B]。 则说明边 e(u,v) 属于A - > B 的最短路径。
(disA[u] 从A->u的最短路)
(disB[v] 从B->v的最短路)
然后从 u - > v 建边,容量为1,跑个最大流板子即可。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
#define rep(i, a, b) for(int i(a); i <= (b); ++i)
#define dec(i, a, b) for(int i(a); i >= (b); --i)
#define MP make_pair
const int INF = 0x3f3f3f;
const int N = 100000 + 10;
const int M = 10000 + 10;
const int Q = 1000 + 10;
const int A = 500 + 10;
struct P{
int v,w,next;
}G[Q*Q],ss[Q*Q],se[Q*Q];
int Head[Q],hs[Q],he[Q],dis[Q];
int disA[Q],disB[Q],vis[Q];
int n,m,tot,tot_s,tot_e;
void init(void){
tot = tot_e = tot_s = 0;
memset(Head,-1,sizeof(Head));
memset(hs,-1,sizeof(hs));
memset(he,-1,sizeof(he));
rep(i,1,n) disA[i] = disB[i] = INF;
}
void add(P e[],int head[],int &cnt,int u,int v,int w){
e[cnt].v = v;
e[cnt].w = w;
e[cnt].next = head[u];
head[u] = cnt++;
}
void build_G(int st,int ed){
for(int i=hs[st];i != -1 ;i=ss[i].next){
int v = ss[i].v,w = ss[i].w;
if(v != -1){
if(disA[st] + disB[v] + w == disA[ed]){
add(G,Head,tot,st,v,1);
add(G,Head,tot,v,st,0);
}
ss[i].v = -1;
build_G(v,ed);
}
}
}
bool bfs(int st,int ed){
queue<int> que;
memset(dis,-1,sizeof(dis));
dis[st] = 0;
que.push(st);
while(que.size()){
int u = que.front();
que.pop();
for(int i = Head[u] ;i != -1 ;i = G[i].next){
int v = G[i].v, w = G[i].w;
if(w>0 && dis[v]==-1){
dis[v] = dis[u] + 1;
if(v == ed) return true;
que.push(v);
}
}
}
return false;
}
int dfs(int u,int ed,int low){
int tem,res=0;
if(u == ed) return low;
for(int i=Head[u] ;i!=-1 ;i = G[i].next){
int v = G[i].v, w = G[i].w;
if(w>0 && dis[u] + 1 == dis[v]){
tem = dfs(v,ed,min(low,w));
if(tem>0){
G[i].w -= tem;
G[i^1].w += tem;
res += tem;
if(res == low) break;
}
else
dis[v] = -1;
}
}
return res;
}
void spfa(P e[],int head[],int d[],int st){
memset(vis,0,sizeof(vis));
queue<int> que;
que.push(st);
d[st] = 0;
while(que.size()){
int u = que.front();
que.pop();
vis[u] = 0;
for(int i=head[u];i!=-1 ;i=e[i].next){
int v = e[i].v,w = e[i].w;
if(d[v] > d[u] + w){
d[v] = d[u] + w;
if(!vis[v]){
vis[v] = 1;
que.push(v);
}
}
}
}
}
void dinic(int st,int ed){
ll ans = 0;
while(bfs(st,ed)){
ans += dfs(st,ed,INF);
}
printf("%I64d\n",ans);
}
int main(){
int T;
scanf("%d",&T);
while(T--){
scanf("%d%d",&n,&m);
init();
while(m--){
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
if(u==v) continue;
add(ss,hs,tot_s,u,v,w);
add(se,he,tot_e,v,u,w);
}
int st,ed;
scanf("%d%d",&st,&ed);
spfa(ss,hs,disA,st);
spfa(se,he,disB,ed);
build_G(st,ed);
dinic(st,ed);
}
return 0;
}