网络流模板55pts,两个点TLE,三个点WA,有简单注释。(普通模板+加强版样例已过)
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <stack>
#define V 30000 //结点数
#define INF 99999999
using namespace std;
typedef long long int ll;//十年OI一场梦,不开ll见祖宗
int n, m, s, t;//分别为 结点数n 边数m 源点编号s 汇点编号t
int thth, toto;//从thth到toto
ll howto;//权值为多少?
int head[V + 5];//head数组存结点
ll countnum = 0;//计数器
/*以下为Dinic算法重点*/
bool vis = true;//表示是否能到达汇点t
ll sum = 0;//存放总流量
bool book[V + 5];
int levelset[V + 5];//保存层次
int nowlevel = 0;//目前的层次
int cur[V + 5];//cur[u]表示上次循环循环到了那条边 即Dinic算法的“当前弧优化”
queue<int>que1;//BFS队列1
queue<int>que2;//BFS队列2
int ls = 0;//目前历遍到的边的编号
/*以上为Dinic算法重点*/
struct edge {
public:
int to;//到哪个结点
ll capa;//容量
ll flow;//流量
ll resid;//残余流量
int next;//next指针指向下一条边
edge() = default;
void init(int t, ll wei, int nexts = -1, int f = 0) {
to = t;
capa = wei;
flow = f;
resid = wei;
next = nexts;
}//加边
};//存边
vector<edge>edgeset;//内存池
void add(int first, int last, ll capacity, int f = 0) {
if (head[first] != -1) {
edgeset[countnum].init(last, capacity, head[first], f);
head[first] = countnum;//头插
}
else { edgeset[countnum].init(last, capacity, -1, f); head[first] = countnum; }
++countnum;
}//加边
/*以下为Dinic算法的核心代码*/
bool bfs() {
for (int i = 1; i <= n; i++)cur[i] = head[i],levelset[i] = 0,book[i]=false;
que1.push(s);
book[s] = true;
while (!que1.empty()) {
while (!que1.empty()) {
ls = head[que1.front()];//遍历边
while (ls != -1) {//一直遍历到末尾
if (book[edgeset[ls].to] == false && edgeset[ls].resid > 0) {
que2.push(edgeset[ls].to);
levelset[edgeset[ls].to] = levelset[que1.front()]+1;
}
ls = edgeset[ls].next;
}
que1.pop();
}
while (!que2.empty()) {
book[que2.front()] = true;
que1.push(que2.front());
que2.pop();
}
++nowlevel;//增加目前层次
}
bool isfindt = book[t];
ls = 0;
nowlevel = 0;
return isfindt;
}//BFS构造层次图
ll dfs(int bh = s, ll a = INF) {//分别为当前结点编号bh和增广路径上的最小容量a
if (bh == t) { vis = true; return a; }
if (a == 0)return a;
ll used = 0;//表示结点用了多少流量,方便多路增广
ll ls = 0;
for (int i = cur[bh]; i != -1; i = edgeset[i].next) {
cur[bh] = i;
if (levelset[bh] != levelset[edgeset[i].to] - 1 || edgeset[i].resid == 0)continue;
if (ls = a < edgeset[i].resid ? dfs(edgeset[i].to, a) : dfs(edgeset[i].to, edgeset[i].resid)) {
used += ls;used = min(used, a);
edgeset[i].flow += ls;
edgeset[i].resid -= ls;
edgeset[i ^ 1].flow -= ls;
edgeset[i ^ 1].resid += ls;
if (used == a)break;
}
}
return used;
}//DFS多路增广
ll Dinic()
{
while (bfs()) {
vis = true;
while (vis) {
vis = false;
sum += dfs();
}
}
return sum;
}//Dinic核心调用函数
/*以上为Dinic算法的核心代码*/
int main() {
ios::sync_with_stdio(0);
cin >> n >> m >> s >> t;
edgeset.resize(m * 4);
for (int i = 1; i <= n; i++)head[i] = -1;
for (int i = 1; i <= m; i++) {
cin >> thth >> toto >> howto;
add(thth, toto, howto);//这个加正向弧
add(toto, thth, 0, howto);//这个加反向弧
}
cout << Dinic();
return 0;
}