简略题意:n个点,m条边,问所有最小割中的最小边数是多少。
经典模型
最大流等于最小割,因此求出最大流即可知道最小割。
问题在于多个最小割时怎么办?
我们对每个边扩容,流量为w的变成w*BIG+1,BIG为一个足够大的容量。那么只有原图边数最小的最小割才是此时的最小割。
原图的最小割容量为ans/BIG,边数为ans%BIG。
#define others
#ifdef poj
#include
#include
#include
#include
#include
#include
#include
#endif // poj
#ifdef others
#include
#endif // others
//#define file
#define all(x) x.begin(), x.end()
using namespace std;
const double eps = 1e-8;
int dcmp(double x) { if(fabs(x)<=eps) return 0; return (x>0)?1:-1;};
typedef long long LL;
struct Dinic {
static const LL maxn = 1e6 + 10;
static const LL maxm = 4e6 + 10;
struct Edge {
LL u, v, next, flow, cap;
} edge[maxm*2];
LL head[maxn], level[maxn], cur[maxn], eg;
void AddEdge(LL u, LL v, LL cap) {
edge[eg] = {u, v, head[u], 0, cap}, head[u] = eg++;
swap(u, v);
edge[eg] = {u, v, head[u], 0, 0}, head[u] = eg++;
}
void init() {
eg = 0;
memset(head, -1, sizeof head);
}
bool makeLevel(LL s, LL t, LL n) {
for(LL i = 0; i < n; i++) level[i] = 0, cur[i] = head[i];
queue q; q.push(s);
level[s] = 1;
while(!q.empty()) {
LL u = q.front();
q.pop();
for(LL i = head[u]; ~i; i = edge[i].next) {
Edge &e = edge[i];
if(e.flow < e.cap && level[e.v] == 0) {
level[e.v] = level[u] + 1;
if(e.v == t) return 1;
q.push(e.v);
}
}
}
return 0;
}
LL findpath(LL s, LL t, LL limit = 1e18) {
if(s == t || limit == 0) return limit;
for(LL i = cur[s]; ~i; i = edge[i].next) {
cur[edge[i].u] = i;
Edge &e = edge[i], &rev = edge[i^1];
if(e.flow < e.cap && level[e.v] == level[s] + 1) {
LL flow = findpath(e.v, t, min(limit, e.cap - e.flow));
if(flow > 0) {
e.flow += flow;
rev.flow -= flow;
return flow;
}
}
}
return 0;
}
LL operator()(LL s, LL t, LL n) {
LL ans = 0;
while(makeLevel(s, t, n)) {
LL flow;
while((flow = findpath(s, t)) > 0) ans += flow;
}
return ans;
}
} dinic;
namespace solver {
const LL maxn = 100011;
LL cas;
LL n, m, s, t;
void solve() {
scanf("%lld", &cas);
for(LL _ = 0; _ < cas; _++) {
scanf("%lld%lld", &n, &m);
scanf("%lld%lld", &s, &t);
dinic.init();
LL MOD = 2560000;
for(LL i = 1; i <= m; i++) {
LL u, v, w;
scanf("%lld%lld%lld", &u, &v, &w);
dinic.AddEdge(u, v, w*MOD+1);
}
printf("%lld\n", dinic(s, t, n + 1)%MOD);
}
}
}
int main() {
solver::solve();
return 0;
}