这个Dinic有什么问题吗
  • 板块学术版
  • 楼主strcmp
  • 当前回复1
  • 已保存回复1
  • 发布时间2022/1/30 13:34
  • 上次更新2023/10/28 10:03:40
查看原帖
这个Dinic有什么问题吗
551861
strcmp楼主2022/1/30 13:34

网络流模板55pts,两个点TLETLE,三个点WAWA,有简单注释。(普通模板+加强版样例已过)

#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;
}
2022/1/30 13:34
加载中...