思路:这天显然是要求从最短路走,然后就是问在边不重复走的情况下,有多少条从源点到汇点的路径,由于边不重复,所以就是每条边的可行流量为1,接下来就是网络流的问题了。但是由于开始不会SAP只会写DINIC,所以TLE了一天,最后学了下下SAP,,,勉强给过了这题,,,还是太弱了QWQ!!!
/*****************************************
Author :Crazy_AC(JamesQi)
Time :2015
File Name :
*****************************************/
// #pragma comment(linker, "/STACK:1024000000,1024000000")
#include <iostream>
#include <algorithm>
#include <iomanip>
#include <sstream>
#include <string>
#include <stack>
#include <queue>
#include <deque>
#include <vector>
#include <map>
#include <set>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
#include <limits.h>
using namespace std;
#define MEM(a,b) memset(a,b,sizeof a)
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int,int> ii;
const int inf = 1 << 30;
const int INF = 0x3f3f3f3f;
const int MOD = 1e9 + 7;
inline int Readint(){
char c = getchar();
while(!isdigit(c)) c = getchar();
int x = 0;
while(isdigit(c)){
x = x * 10 + c - '0';
c = getchar();
}
return x;
}
const int maxm = 333333;
const int maxn = 2222;
struct node{
int v,cost;
};
vector<node> G[maxn];
struct Edge{
int v,cap,nxt;
}E[maxm];
int head[maxn];
int cur[maxn];
int pre[maxn];
int lev[maxn];
int gap[maxn];
int NV,cnt,n,m,vs,vt;
int dist[maxn];
bool visit[maxn];
void Add(int u,int v,int c){
E[cnt].v = v;E[cnt].cap = c;E[cnt].nxt = head[u];head[u] = cnt++;
E[cnt].v = u;E[cnt].cap = 0;E[cnt].nxt = head[v];head[v] = cnt++;
}
void SPFA(){
memset(dist, INF,sizeof dist);
memset(visit, false,sizeof visit);
dist[vs] = 0;
queue<int> que;
que.push(vs);
while(!que.empty()){
int u = que.front();
que.pop();
visit[u] = false;
for (int i = G[u].size() - 1;i >= 0;--i){
int v = G[u][i].v;
int w = G[u][i].cost;
if (dist[v] > dist[u] + w){
dist[v] = dist[u] + w;
if (!visit[v]){
visit[v] = true;
que.push(v);
}
}
}
}
}
int SAP(int vs,int vt){
memset(lev, 0,sizeof lev);
memset(pre, -1,sizeof pre);
memset(gap, 0,sizeof gap);
// memcpy(cur, head,sizeof head);
for (int i = 1;i <= n;++i) cur[i] = head[i];
int u = pre[vs] = vs;
int maxflow = 0,aug = -1;
gap[0] = NV;
while(lev[vs] < NV){
loop:
for (int &i = cur[u];i != -1;i = E[i].nxt){
int v = E[i].v;
if (E[i].cap && lev[u] == lev[v] + 1){
aug == -1?(aug = E[i].cap):(aug = min(aug,E[i].cap));
pre[v] = u;
u = v;
if (v == vt){
maxflow += aug;
for (u = pre[v];v != vs;v = u,u = pre[u]){
E[cur[u]].cap -= aug;
E[cur[u] ^ 1].cap += aug;
}
aug = -1;
}
goto loop;
}
}
int minlev = NV;
for (int i = head[u];i != -1;i = E[i].nxt){
int v = E[i].v;
if (E[i].cap && minlev > lev[v]){
cur[u] = i;//保存当前弧
minlev = lev[v];
}
}
if (--gap[lev[u]] == 0) break;
/*更新gap数组后如果出现断层,则直接退出*/
lev[u] = minlev + 1;/*重新更新标号*/
gap[lev[u]]++;/*距离标号为lev[u]的点的个数+1*/
u = pre[u];/*转当前点的前驱节点继续寻找可行弧*/
}
return maxflow;
}
int main()
{
// freopen("in.txt","r",stdin);
// freopen("out.txt","w",stdout);
int t;
int u,v,d;
scanf("%d",&t);
while(t--){
scanf("%d%d",&n,&m);
for (int i = 1;i <= n;i++)
G[i].clear();
for (int i = 1;i <= m;i++){
scanf("%d%d%d",&u,&v,&d);
if (u == v) continue;
node p;
p.v = v;
p.cost = d;
G[u].push_back(p);
}
scanf("%d%d",&vs,&vt);
SPFA();
cnt = 0;
NV = n;
memset(head, -1,sizeof head);
for (int i = 1;i <= n;i++){
for (int j = 0;j < G[i].size();++j){
if (dist[G[i][j].v] == dist[i] + G[i][j].cost)
Add(i,G[i][j].v,1);
}
}
printf("%d\n",SAP(vs,vt));
}
return 0;
}