Consider a network G=(V,E) with source s and sink t. An s-t cut is a partition of nodes set V into two parts such that s and t belong to different parts. The cut set is the subset of E with all edges connecting nodes in different parts. A minimum cut is the one whose cut set has the minimum summation of capacities. The size of a cut is the number of edges in the cut set. Please calculate the smallest size of all minimum cuts.
题意:求最少边的最小割
添加边的时候流量改为w*(m + 1) + 1,跑一遍最大流flow,最小割为flow/(m+1),最少的最小割边数为flow%(m+1)
把边扩大m+1倍后,剩下的1代表割的边数,并且它不会超过m,不会影响最小割值
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <queue>
using namespace std;
typedef long long LL;
void read(int &x) {
char c;bool flag = 0;
while((c=getchar())<'0'||c>'9') flag |= (c=='-');
x=c-'0';while((c=getchar())>='0'&&c<='9') x = (x<<3)+(x<<1)+c-'0';
flag?x=-x:x;
}
#define MAXX 6000
#define N 300
const int inf = ~0u>>2;
struct E {
int to,flow,next;
E(int to=0,int flow=0,int next=0):to(to),flow(flow),next(next){}
}g[MAXX];
int tot = 1,fr[N];
void Add(int from,int to,int flow) {
//cout<<"E:"<<from<<" "<<to<<" "<<flow<<"\n";
g[++tot] = E(to,flow,fr[from]);
fr[from] = tot;
g[++tot] = E(from,0,fr[to]);
fr[to] = tot;
}
int n,k,m;
int d[N],st,ed;
bool bfs() {
memset(d,-1,sizeof d);
queue<int> q;
q.push(st); d[st] = 0;
while(q.size()) {
int t = q.front(); q.pop();
for (int i = fr[t]; i; i = g[i].next) {
int to = g[i].to;
if(d[to] == -1 && g[i].flow) {
d[to] = d[t]+1;
q.push(to);
}
}
}
return d[ed] != -1;
}
int dfs(int t,int mf) {
if(t == ed || mf == 0) return mf;
int tmp = 0;
for (int i = fr[t]; i; i = g[i].next) {
if(mf == 0 || g[i].flow == 0 || d[g[i].to] != d[t]+1) continue;
int f = dfs(g[i].to,min(mf,g[i].flow));
mf -= f; tmp += f;
g[i].flow -= f; g[i^1].flow += f;if(mf==tmp) return mf;
}
if(mf) d[t] = -1;
return tmp;
}
int Dinic(int s,int t) {
st = s; ed = t;int max_flow = 0;
while(bfs()) max_flow += dfs(st,inf);
return max_flow;
}
int main() {
int T,s,t; cin >> T;
while (T--) {
cin >> n >> m >> s >> t;
tot = 1;
for (int i = 0; i <= n+1; i++) fr[i] = 0;
for (int i = 1; i <= m; i++) {
int u,v,w;
cin >> u >> v >> w;
Add(u,v,w*(m+1)+1);
// Add(v,u,0);
}
printf("%d\n",Dinic(s,t)%(m+1));
}
return 0;
}