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; }