From 585da08a4eeea343cd345d6a82a39df468628326 Mon Sep 17 00:00:00 2001 From: zscoder Date: Sat, 22 Oct 2016 09:17:10 +0800 Subject: [PATCH] Added Min Cost Flow and Gaussian Elimination --- Data Structures Class Template.cpp | 168 +++++++++++++++++++++++++++++ 1 file changed, 168 insertions(+) diff --git a/Data Structures Class Template.cpp b/Data Structures Class Template.cpp index 51ca8e9..c28e011 100644 --- a/Data Structures Class Template.cpp +++ b/Data Structures Class Template.cpp @@ -1349,6 +1349,7 @@ struct Tree for(int i = 0; i < adj[u].size(); i++) { int v = adj[u][i].v; + if(v == p) continue; dfsstartend(v, u); } en[u] = ++timer; @@ -2960,6 +2961,173 @@ struct plane }; //End Geometry +//Start MinCostFlow (yunkai version) +struct Edge{ + int u, v; + long long cap, cost; + + Edge(int _u, int _v, long long _cap, long long _cost){ + u = _u; v = _v; cap = _cap; cost = _cost; + } +}; + +struct MinCostFlow{ + int n, s, t; + long long flow, cost; + vector > graph; + vector e; + vector dist, potential; + vector parent; + bool negativeCost; + + MinCostFlow(int _n){ + // 0-based indexing + n = _n; + graph.assign(n, vector ()); + negativeCost = false; + } + + void addEdge(int u, int v, long long cap, long long cost, bool directed = true){ + if(cost < 0) + negativeCost = true; + + graph[u].push_back(e.size()); + e.push_back(Edge(u, v, cap, cost)); + + graph[v].push_back(e.size()); + e.push_back(Edge(v, u, 0, -cost)); + + if(!directed) + addEdge(v, u, cap, cost, true); + } + + pair getMinCostFlow(int _s, int _t){ + s = _s; t = _t; + flow = 0, cost = 0; + + potential.assign(n, 0); + if(negativeCost){ + // run Bellman-Ford to find starting potential + dist.assign(n, 1LL<<62); + for(int i = 0, relax = false; i < n && relax; i++, relax = false){ + for(int u = 0; u < n; u++){ + for(int k = 0; k < graph[u].size(); k++){ + int eIdx = graph[u][i]; + int v = e[eIdx].v, cap = e[eIdx].cap, w = e[eIdx].cost; + + if(dist[v] > dist[u] + w && cap > 0){ + dist[v] = dist[u] + w; + relax = true; + } } } } + + for(int i = 0; i < n; i++){ + if(dist[i] < (1LL<<62)){ + potential[i] = dist[i]; + } } } + + while(dijkstra()){ + flow += sendFlow(t, 1LL<<62); + } + + return make_pair(flow, cost); + } + + bool dijkstra(){ + parent.assign(n, -1); + dist.assign(n, 1LL<<62); + priority_queue, greater > pq; + + dist[s] = 0; + pq.push(ii(0, s)); + + + while(!pq.empty()){ + int u = pq.top().second; + long long d = pq.top().first; + pq.pop(); + + if(d != dist[u]) continue; + + for(int i = 0; i < graph[u].size(); i++){ + int eIdx = graph[u][i]; + int v = e[eIdx].v, cap = e[eIdx].cap; + int w = e[eIdx].cost + potential[u] - potential[v]; + + if(dist[u] + w < dist[v] && cap > 0){ + dist[v] = dist[u] + w; + parent[v] = eIdx; + + pq.push(ii(dist[v], v)); + } } } + + // update potential + for(int i = 0; i < n; i++){ + if(dist[i] < (1LL<<62)) + potential[i] += dist[i]; + } + + return dist[t] != (1LL<<62); + } + + long long sendFlow(int v, long long curFlow){ + if(parent[v] == -1) + return curFlow; + int eIdx = parent[v]; + int u = e[eIdx].u, w = e[eIdx].cost; + + long long f = sendFlow(u, min(curFlow, e[eIdx].cap)); + + cost += f*w; + e[eIdx].cap -= f; + e[eIdx^1].cap += f; + + return f; + } +}; +//End mincostflow + +//Start Z_{2} gausselim +struct gausselim +{ + ll cnt[61][2]; + int rank; + ll cyc[61]; + ll tmp; + void init() + { + for(int i = 0; i < 61; i++) + { + cyc[i] = cnt[i][0] = cnt[i][1] = 0; + } + rank = tmp = 0; + } + void addval(ll x) + { + for(int i = 0; i < 61; i++) + { + cnt[i][(x>>i)&1]++; + } + } + void add(ll x) + { + tmp|=x; + for(int i = 60; i >= 0; i--) + { + if(x&(1LL<