luogu1345 奶牛的电信

  拆点、最小割的模板题。

  我只想说一点。拆点时不可以下意识地初始化!起点和终点不能直接写编号!写拆点后的Id!

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;

#define In(x) (x) * 2 - 1
#define Out(x) (x) * 2
const int MAX_NODE = 210, MAX_EDGE = 210 * 210 * 2, INF = 0x3f3f3f3f;

struct Dinic
{
private:
    struct Node;
    struct Edge;

    struct Node
    {
        Edge *Head, *DfsFrom;
        int Level;
    }_nodes[MAX_NODE], *Start, *Target;
    int TotNode;

    struct Edge
    {
        Node *To;
        Edge *Next, *Rev;
        int Cap;
    }_edges[MAX_EDGE];
    int _eCount;

    Edge *AddEdge(Node *from, Node *to, int cap)
    {
        Edge *e = _edges + ++_eCount;
        e->To = to;
        e->Cap = cap;
        e->Next = from->Head;
        from->Head = e;
        return e;
    }

    bool Bfs()
    {
        for (int i = 1; i <= TotNode; i++)
            _nodes[i].Level = 0;
        Start->Level = 1;
        static queue<Node*> q;
        q.push(Start);
        while (!q.empty())
        {
            Node *cur = q.front();
            q.pop();
            for (Edge *e = cur->Head; e; e = e->Next)
            {
                if (e->Cap && !e->To->Level)
                {
                    e->To->Level = cur->Level + 1;
                    q.push(e->To);
                }
            }
        }
        return Target->Level;
    }

    int Dfs(Node *cur, int limit)
    {
        if (cur == Target)
            return limit;
        if (limit == 0)
            return 0;
        int curTake = 0;
        for (Edge *e = cur->DfsFrom; e; e = (cur->DfsFrom) = e->Next)
        {
            if (e->Cap && e->To->Level == cur->Level + 1)
            {
                int nextTake = Dfs(e->To, min(limit - curTake, e->Cap));
                curTake += nextTake;
                e->Cap -= nextTake;
                e->Rev->Cap += nextTake;
            }
            if (curTake == limit)
                break;
        }
        return curTake;
    }

public:
    void Init(int n, int s, int t)
    {
        TotNode = n;
        Start = _nodes + s;
        Target = _nodes + t;
    }

    void Build(int uId, int vId, int cap)
    {
        Node *u = _nodes + uId, *v = _nodes + vId;
        Edge *e1 = AddEdge(u, v, cap), *e2 = AddEdge(v, u, 0);
        e1->Rev = e2;
        e2->Rev = e1;
    }

    int MaxFlow()
    {
        int ans = 0;
        while (Bfs())
        {
            for (int i = 1; i <= TotNode; i++)
                _nodes[i].DfsFrom = _nodes[i].Head;
            ans += Dfs(Start, INF);
        }
        return ans;
    }
}g;

int main()
{
    int totNode, totEdge, s, t;
    scanf("%d%d%d%d", &totNode, &totEdge, &s, &t);
    g.Init(totNode * 2, Out(s), In(t));//!!!!!!!!!!!!!!!!!!!!!!!!!!
    for (int i = 1; i <= totNode; i++)
        g.Build(In(i), Out(i), 1);
    for (int i = 1; i <= totEdge; i++)
    {
        int u, v;
        scanf("%d%d", &u, &v);
        g.Build(Out(u), In(v), INF);
        g.Build(Out(v), In(u), INF);
    }
    printf("%d\n", g.MaxFlow());
    return 0;
}

  

posted @ 2018-08-15 21:36  headboy2002  阅读(100)  评论(0编辑  收藏  举报