#include
#define mst(a,b) memset(a,b,sizeof(a))
#define For(i, k, j) for(register int i = (k); i <= (j); i++)
#define INF 2147483647
using namespace std;
inline int read()
{
int num = 0;
char c=' ';
bool flag = 1;
for(;c>'9'||c<'0';c=getchar()) if(c=='-') flag = -1;
for(;c>='0'&&c<='9';num=(num<<1)+(num<<3)+c-48,c=getchar());
return num * flag;
}
#define N 201
#define M 100001
int g[N][N]; //残量网络
//int f[N][N]; //实流网络
int pre[N]; // 记录每个点的前驱
bool vis[N]; // 记录每个点是否被访问过
int n, m;
bool bfs(int s, int t) {
mst(pre, -1); mst(vis, 0);
queue < int > q;
vis[s] = 1;
q.push(s);
while(!q.empty()) {//无脑宽搜
int now = q.front();
q.pop();
For(i, 1, n) {//找增广路
if(!vis[i] && g[now][i] > 0) { //now点有边连到i且i未被访问过
vis[i] = 1;
pre[i] = now;//记录前驱
if(i == t) {
return 1;
}
q.push(i);
}
}
}
return 0;
}
inline int EK(int s, int t) {
int v, u, d, maxflow = 0;
while(bfs(s, t)) { //可以增广
v = t, d = INF;//找可增量d
while(v != s) {
u = pre[v]; // u记录v的前驱
d = min(d, g[u][v]);
v = u;
}
maxflow += d;
v = t;
while(v != s) {
u = pre[v];
g[u][v] -= d; //残量网络中的正向边减流
g[v][u] += d; //残量网络中的反向边加流
// if(f[v][u] > 0) {//实流网络中是反向边
// f[v][u] -= d;//减流
// } else {
// f[u][v] += d;//否则加流
// }
v = u;
}
}
return maxflow;
}
int main()
{
n = read(), m = read();
int s = 1, t = n;
For(i, 1, m) {
int u = read(), v = read(), w = read();
g[u][v] += w;
}
printf("%d\n", EK(s, t));
return 0;
}
ISAP:
#include
#define mst(a,b) memset(a,b,sizeof(a))
#define For(i, k, j) for(register int i = (k); i <= (j); i++)
#define INF 2147483647
using namespace std;
inline int read()
{
int num = 0;
char c=' ';
bool flag = 1;
for(;c>'9'||c<'0';c=getchar()) if(c=='-') flag = -1;
for(;c>='0'&&c<='9';num=(num<<1)+(num<<3)+c-48,c=getchar());
return num * flag;
}
#define N 50001
#define M 500001
int fir[N]; //邻接表头
int h[N]; // 当前节点的高度
int g[N]; //g[i]:高度为i的结点个数、
int pre[N]; //前驱
int tot = 0;
struct Edge { //混合网络 的边结构体
int to, nxt;
int cap; //容量
int flow; //当前流量
}e[M];
inline void addedge(int u, int v, int c) {
e[tot].to = v;
e[tot].cap = c;
e[tot].flow = 0;
e[tot].nxt = fir[u];
fir[u] = tot++;
}
void set_h(int t, int n) {
queue q;
mst(h, -1); mst(g, 0);
h[t] = 0;
q.push(t);
while(!q.empty()) {//打宽搜打的满脸无奈
int v = q.front();
q.pop();
++g[h[v]];
for(int i = fir[v]; ~i; i = e[i].nxt) {
int u = e[i].to;
if(h[u] == -1) {
h[u] = h[v] + 1;
q.push(u);
}
}
}
// cout << "seth over" << endl;
}
int n, m;
int ISAP(int s, int t, int n) { //s:源点 t:汇点 n:边数
set_h(t, n);
int ans = 0, u = s;
int d;
while(h[s] < n) {
int i = fir[u];
if(u == s) {
d = INF;
}
for(; ~i; i = e[i].nxt) {//搜当前点的邻接边
int v = e[i].to;
if(e[i].cap > e[i].flow && h[u] == h[v] + 1) {//沿着有可增量和高度减一的方向搜
u = v;
pre[v] = i;
d = min(d, e[i].cap - e[i].flow);//找可增量d
if(u == t) {//到达汇点
while(u != s) { //往源点搜
int j = pre[u];
e[j].flow += d;//正向边流量加
e[j^1].flow -= d;//反向边流量减
u = e[j^1].to;
}
ans += d;
d = INF;
}
break;//找到一条可行边,退出当前搜索,向前走
}
}
if(i == -1) {//搜完了当前节点的所有边还停在原地
if(--g[h[u]] == 0) { //ISAP的优化
break;
}
int hmin = n - 1;
for(int j = fir[u]; ~j; j = e[j].nxt) {//搜u的邻接边
if(e[j].cap > e[j].flow) {
hmin = min(hmin, h[e[j].to]); //取最小值
}
}
h[u] = hmin + 1; //重新标高
++g[h[u]];
if(u != s) {
u = e[pre[u] ^ 1].to;
}
}
}
return ans;
}
int main()
{
n = read(), m = read();
int s = read(), t = read();
mst(fir, -1);
For(i, 1, m) {
int u = read(), v = read(), w = read();
addedge(u, v, w); //添加正向边,即当前边的残余流量
addedge(v, u, 0); //添加反向边,即实流网络中当前流量
}
printf("%d\n", ISAP(s, t, n));
return 0;
}