先求出最短路径,然后用最短路径上的边构建一个新图,在新图上求最小割。
#include <iostream>
#include <queue>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <vector>
using namespace std;
int const N= 1010, M= 200010;
int n, m;
int const inf= 0x7fffffff;
int res;
struct Node{
Node(){}
Node(int a,int b ):adj(a), wt(b) {}
int adj, wt; };
struct cmp{
bool operator()( Node a, Node b ){
return a.wt> b.wt; }
};
vector<Node> mata[N], matb[N];
int S, T;
int dista[N], distb[N];
int dijks( int s, int t, int d[], vector<Node> mat[] ){
for( int i= 0; i<= n; ++i ) d[i]= inf;
d[s]= 0;
priority_queue<Node, vector<Node>, cmp> que;
que.push( Node( s, 0 ) );
while( !que.empty() ){
int u= que.top().adj, w= que.top().wt; que.pop();
if( w!= d[u] ) continue;
for( size_t i= 0; i< mat[u].size(); ++i ){
int v= mat[u][i].adj, t= mat[u][i].wt;
if( d[u]+ t< d[v] ){
d[v]= d[u]+ t;
que.push( Node( v, d[v] ) );
}
}
}
return d[t];
}
struct Edge{
int flow, adj;
Edge* next;
}tb[M];
Edge* mat[N], *Pre[N];
int cnt= -1;
inline Edge* reserve( Edge* p ){
return tb+ ( (p- tb)^ 1 );
}
inline void add( int u, int v, int c ){
++cnt;
tb[cnt].adj= v; tb[cnt].flow= c;
tb[cnt].next= mat[u]; mat[u]= tb+ cnt;
++cnt;
tb[cnt].adj= u; tb[cnt].flow= 0;
tb[cnt].next= mat[v]; mat[v]= tb+ cnt;
}
int que[M], ht[N], flag[N], path[N], head, tail;
int bfs(){
que[0]= S; head= 0; tail= 0;
for( int i= 0; i<= n; ++i ) ht[i]= -1; ht[S]= 0;
while( head<= tail ){
int u= que[head++];
for( Edge* p= mat[u]; p; p= p->next )
if( ht[p->adj]== -1 && p->flow ){
ht[p->adj]= ht[u]+ 1;
que[++tail]= p->adj;
}
}
return ht[T]!= -1;
}
int dfs( int u, int flow ){
if( u== T ) return flow;
int tf= 0, f;
for( Edge* p= mat[u]; p; p= p->next )
if( ht[p->adj]== ht[u]+ 1 && p->flow && flow> tf &&
( f= dfs( p->adj, min( p->flow, flow- tf ) ) ) ){
reserve( p )->flow+= f;
p->flow-= f;
tf+= f;
}
if( tf== 0 ) ht[u]= -1;
return tf;
}
void build(){
cnt= -1;
for( int i= 0; i<= n; ++i ) mat[i]= 0;
for( int u= 1; u<= n; ++u )
for( size_t i= 0; i< mata[u].size(); ++i ){
int v= mata[u][i].adj, w= mata[u][i].wt;
if( dista[u]+ w+ distb[v]== res ){
add( u, v, 1 );
}
}
}
int main(){
int test;
scanf("%d",&test );
while( test-- ){
scanf("%d%d",&n,&m );
for( int i= 0; i< m; ++i){
int u, v, d;
scanf("%d%d%d", &u, &v, &d );
mata[u].push_back( Node(v,d) );
matb[v].push_back( Node(u,d) );
}
scanf("%d%d", &S, &T );
dijks( S, T, dista, mata );
res= dijks( T, S, distb, matb );
build();
int ans= 0;
while( bfs() ) ans+= dfs( S, 0x7fffffff );
printf("%d\n", ans );
for( int i= 0; i<= n; ++i )
mata[i].clear(), matb[i].clear();
}
return 0;
}