网络流
Skyzhou666 · · 算法·理论
链式前向星
前置内容:网络流所使用的数据结构
个人理解为带一个记录每个点最后一个边的head数组,和一个存边的链表,next表示这一个点的下一个边的位置
#include <iostream>
#include <cstring>
#define MAXN 1001
using namespace std;
struct Edge
{
int next, to, w;
} edge[MAXN];
int n, m, s, t, head[MAXN], cnt;
void add(int u, int v, int w)
{
edge[cnt].next = head[u];
edge[cnt].to = v;
edge[cnt].w = w;
head[u] = cnt++;
}
int main()
{
memset(head, -1, sizeof(head));
cin >> n >> m >> s >> t;
for(int x = 0; x < m; x++)
{
int u, v, w;
cin >> u >> v >> w;
add(u, v, w);
}
for(int x = 1; x <= n; x++)
{
for(int y = head[x]; y >= 0; y = edge[y].next) cout << y << " ";
cout << endl;
}
return 0;
}
下面这篇文章讲得不错(
链式前向星
网络流
模板题:P3376
这里用的是Edmond-Karp(EK)算法,就是Ford-Fulkerson(FF)算法的bfs版本,效率高,码量不大,不过速度最快的还是Dinic算法(不会
大概就是建反向边,不断寻找增广路
#include <iostream>
#include <cstring>
#include <queue>
#include <cstdio>
#define MAXN 10001
#define INF 0x7fffffff
#define LL long long
using namespace std;
struct Edge
{
LL next, to, w;
} edge[MAXN];
LL n, m, s, t, head[MAXN], cnt = 1, last[MAXN], flow[MAXN];
void add(LL u, LL v, LL w)
{
++cnt;
edge[cnt].next = head[u];
edge[cnt].to = v;
edge[cnt].w = w;
head[u] = cnt;
}
LL bfs()
{
memset(last, -1, sizeof(last));
queue <LL> q;
q.push(s);
flow[s] = INF;
while(!q.empty())
{
int u = q.front(); q.pop();
//cout << u << " ";
if(u == t) break;
for(LL x = head[u]; x > 0; x = edge[x].next)
{
LL v = edge[x].to, w = edge[x].w;
//cout << v << endl;
if(w > 0 && last[v] == -1)
{
last[v] = x;
flow[v] = min(flow[u], w);
q.push(v);
}
}
}
return last[t] != -1;
}
LL EK()
{
LL ans = 0;
while(bfs())
{
ans += flow[t];
//cout << "Flow: " << flow[t] << endl;
for(LL x = t; x != s; x = edge[last[x] ^ 1].to)
{
edge[last[x]].w -= flow[t];
edge[last[x]^1].w += flow[t];
}
}
return ans;
}
int main()
{
//freopen("test.in", "r", stdin);
memset(head, -1, sizeof(head));
cin >> n >> m >> s >> t;
for(LL x = 0; x < m; x++)
{
int u, v, w;
cin >> u >> v >> w;
add(u, v, w);
add(v, u, 0);
}
cout << EK() << endl;
fclose(stdin);
return 0;
}
板子题卡long long,但不卡EK