思路:这天显然是要求从最短路走,然后就是问在边不重复走的情况下,有多少条从源点到汇点的路径,由于边不重复,所以就是每条边的可行流量为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; }