图示有向的,A->B,每条路只能走一次,而且由于时间关系只能走最短的路径,点是可以多次经过的。求最多有多少条不同的枯井从A到B。
抛开最后那个条件,其实就是最大流,加上条件之后呢就是先正反个求一遍最短路,然后枚举边,如果该边是最短路径上面的就添加到网络流的图中去,容量为1。
/***************************************** Author :Crazy_AC(JamesQi) Time :2016 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 <cstdio> #include <cstring> #include <cmath> #include <cstdlib> #include <climits> using namespace std; #define MEM(x,y) memset(x, y,sizeof x) #define pk push_back typedef long long LL; typedef unsigned long long ULL; typedef pair<int,int> ii; typedef pair<ii,int> iii; const double eps = 1e-10; const int inf = 1 << 30; const int INF = 0x3f3f3f3f; const int MOD = 1e9 + 7; const int maxn = 1010; const int maxm = 3e5 + 10; int head[maxn], pnt[maxm], d1[maxn], w[maxm], nxt[maxm], d2[maxn]; int ecnt; void addedge(int u,int v,int cost) { pnt[ecnt] = v, w[ecnt] = cost, nxt[ecnt] = head[u], head[u] = ecnt++; } int n, m; void spfa(int s,int t,int *d) { bool vis[maxn]; memset(vis, false,sizeof vis); // memset(d, INF,sizeof d); for (int i = 1;i <= n;++i) d[i] = INF; queue<int> que; que.push(s); vis[s] = true; d[s] = 0; while(!que.empty()) { int u = que.front(); que.pop(); vis[u] = false; for (int i = head[u];i != -1;i = nxt[i]) { int v = pnt[i]; if (d[v] > d[u] + w[i]) { d[v] = d[u] + w[i]; if (!vis[v]) { vis[v] = true; que.push(v); } } } } } struct Edge{ int from, to, cap, flow; Edge(){} Edge(int from,int to,int cap,int flow) : from(from),to(to),cap(cap),flow(flow){} }; struct Dinic{ int n, m, s, t; bool vis[maxn]; int dis[maxn]; vector<Edge> edges; vector<int> G[maxn]; void init(int n) { this->n = n; for (int i = 0;i <= n;++i) G[i].clear(); edges.clear(); } void addedge(int u,int v,int c) { edges.push_back(Edge(u, v, c, 0)); edges.push_back(Edge(v, u, 0, 0)); m = (int)edges.size(); G[u].push_back(m - 2); G[v].push_back(m - 1); } bool spfa() { queue<int> que; memset(dis, -1,sizeof dis); dis[s] = 0; que.push(s); while(!que.empty()) { int u = que.front(); que.pop(); for (int i = 0;i < G[u].size();++i) { Edge& e = edges[G[u][i]]; if (e.cap > e.flow && dis[e.to] == -1) { dis[e.to] = dis[u] + 1; que.push(e.to); } } } return dis[t] != -1; } int dfs(int u,int a) { if (u == t || a == 0) return a; int ret = 0, f; for (int i = 0;i < G[u].size();++i) { Edge& e = edges[G[u][i]]; if (dis[e.to] > dis[u] && (f = dfs(e.to, min(a, e.cap - e.flow))) > 0) { ret += f; a -= f; e.flow += f; edges[G[u][i]^1].flow -= f; if (a == 0) break; } } return ret; } int MaxFlow(int s,int t) { this->s = s, this->t = t; int ret = 0; while(spfa()) { ret += dfs(s, INF); } return ret; } }; Dinic dinic; struct Item{ int x,y,z; }fuck[maxm]; int main() { // freopen("in.txt","r",stdin); // freopen("out.txt","w",stdout); int tt; scanf("%d",&tt); while(tt--) { scanf("%d%d",&n,&m); memset(head, -1,sizeof head); ecnt = 0; int u, v, cost; for (int i = 1;i <= m;++i) { scanf("%d%d%d",&u,&v,&cost); fuck[i].x = u, fuck[i].y = v, fuck[i].z = cost; if (u == v) continue; addedge(u, v, cost); // addedge(v, u, cost); } scanf("%d%d",&u,&v); spfa(u, v, d1); memset(head, -1,sizeof head);ecnt = 0; for (int i = 1;i <= m;++i) { if (fuck[i].x == fuck[i].y) continue; addedge(fuck[i].y, fuck[i].x, fuck[i].z); } spfa(v, u, d2); int Mindis = d1[v]; // cout << Mindis << endl; dinic.init(n); int s = u, t = v; for (u = 1;u <= n;++u) { for (int i = head[u];i != -1;i = nxt[i]) { if (d2[u] + d1[pnt[i]] + w[i] == Mindis) { dinic.addedge(pnt[i], u, 1); // dinic.addedge(pnt[i], u, 1); } } } printf("%d\n", dinic.MaxFlow(s, t)); } return 0; }