Skip to content

Commit

Permalink
Added Min Cost Flow and Gaussian Elimination
Browse files Browse the repository at this point in the history
  • Loading branch information
zscoder authored Oct 22, 2016
1 parent 69d86b6 commit 585da08
Showing 1 changed file with 168 additions and 0 deletions.
168 changes: 168 additions & 0 deletions Data Structures Class Template.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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<vector<int> > graph;
vector<Edge> e;
vector<long long> dist, potential;
vector<int> parent;
bool negativeCost;

MinCostFlow(int _n){
// 0-based indexing
n = _n;
graph.assign(n, vector<int> ());
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<long long, long long> 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<ii, vector<ii>, greater<ii> > 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<<i))
{
if(cyc[i]==0)
{
cyc[i] = x;
rank++;
break;
}
}
x = min(x, (x^cyc[i]));
}
}
};
//End Z_{2} gausselim

/* TO-DO LIST :
1. SQRT DECOMP (MO)
2. SQRT DECOMP (REAL)
Expand Down

0 comments on commit 585da08

Please sign in to comment.