Skip to content

Latest commit

 

History

History
448 lines (389 loc) · 9.5 KB

graph.rst

File metadata and controls

448 lines (389 loc) · 9.5 KB

Graph

Graph

int const N = 100010;
int const M = 1000010;
struct Edges {
  int u, next;
} e[M];
int p[N], idx;
void init() { clr(p, 0xff); idx = 0; }
void addedge(int u, int v) { e[idx].u = v, e[idx].next = p[u], p[u] = idx++; }

Cut-Vertex and Bridge

//+ DSU/Stack to maintain the size of each component
//* Cut-Vertex: (u) if (sc[u] > 1)
//* Cut-Bridge: (u, v) if (low[v] > dfn[u]) *warning: parallel_edges
struct CutVertex {
  int dfn[N], low[N], sc[N], cnt;
  void dfs(int u, int ori, int pre) {
    dfn[u] = low[u] = ++cnt;
    for (int i = p[u]; ~i; i = e[i].next) {
      int v = e[i].u;
      if (!dfn[v]) {
        dfs(v, ori, i);
        low[u] = min(low[u], low[v]);
        if (low[v] >= dfn[u]) ++sc[u];
      }
      else if ((i ^ 1) != pre) { // ensure (e[(u, v)] ^ e[(v, u)]) == 1
        low[u] = min(low[u], dfn[v]);
      }
    }
    if (u != ori) ++sc[u];
  }
  void solve() {
    cnt = 0, clr(dfn, 0), clr(sc, 0);
    Rep(i, n) if (!dfn[i]) dfs(i, i, -1);
  }
};

BCC

_static/bcc.png

// BCC(Edge)
int col[N], cc; // clr(col, 0), cc = 0;
void dfs(int u) {
  if (!col[u]) col[u] = ++cc;
  for (int i = p[u]; ~i; i = e[i].next) {
    int v = e[i].u;
    if (!col[v]) {
      if (cv.low[v] > cv.dfn[u]) col[v] = ++cc;
      else col[v] = col[u];
      dfs(v);
    }
  }
}
// BCC(Vertex)
bool vis[N]; // clr(vis, 0);
int col[M], cc; // clr(col, 0), cc = 0;
void dfs(int u, int pc) {
  vis[u] = 1;
  for (int i = p[u]; ~i; i = e[i].next) {
    if (!col[i]) {
      int v = e[i].u;
      if (cv.low[v] >= cv.dfn[u]) col[i] = col[i ^ 1] = ++cc;
      else col[i] = col[i ^ 1] = pc;
      if (!vis[v]) dfs(v, col[i]);
    }
  }
}

SCC (tarjan)

struct SCC {
  int top, cnt, cc, t;
  int st[N], dfn[N], low[N], col[N]; bool vis[N];
  void tarjan(int u) {
    dfn[u] = low[u] = ++cnt;
    st[++top] = u, vis[u] = 1;
    for (int i = p[u]; ~i; i = e[i].next) {
      int v = e[i].u;
      if (!dfn[v]) {
        tarjan(v);
        low[u] = min(low[u], low[v]);
      }
      else if (vis[v]) low[u] = min(low[u], dfn[v]);
    }
    if (dfn[u] == low[u]) {
      do {
        t = st[top--];
        col[t] = cc;
        vis[t] = 0;
      } while (t != u);
      ++cc;
    }
  }
  void solve() {
    top = cnt = cc = 0;
    clr(vis, 0), clr(col, 0), clr(dfn, 0);
    Rep(i, n) if (!dfn[i]) tarjan(i);
  }
};

SCC (floyd)

int n, mp[N][N]; // clr(mp, 0x3f); mp[i][i] = 0;
void floyd() {
  rep(k, n) rep(i, n) rep(j, n)
    mp[i][j] = min(mp[i][j], mp[i][k] + mp[k][j]);
}

dijkstra

priority_queue<pair<int, int> > Q;
int dis[N]; bool vis[N];

void dijkstra(int s) {
  int u, v, w;
  while (!Q.empty()) Q.pop(); clr(vis, 0), clr(dis, 0x3f);
  Q.push(make_pair(0, s)), dis[s] = 0;
  while (!Q.empty()) {
    pair<int, int> tmp = Q.top(); Q.pop();
    if (vis[u = tmp.second]) continue;
    else vis[u] = true;
    for (int i = p[u]; ~i; i = e[i].next) {
      v = e[i].u, w = e[i].w;
      if (!vis[v] && dis[u] + w < dis[v]) {
        dis[v] = dis[u] + w;
        Q.push(make_pair(-dis[v], v));
      }
    }
  }
}

SPFA

int dis[N]; bool vis[N];
int Q[N * N];

void spfa(int s) {
  int u, v, w, l(0), h(0);
  clr(vis, 0), clr(dis, 0x3f);
  Q[h++] = s, dis[s] = 0;
  while (l < h) {
    u = Q[l++];
    vis[u] = 0;
    for (int i = p[u]; ~i; i = e[i].next) {
      v = e[i].u, w = e[i].w;
      if (dis[u] + w < dis[v]) {
        dis[v] = dis[u] + w;
        if (!vis[v]) {
          vis[v] = 1;
          Q[h++] = v;
        }
      }
    }
  }
}

Hungary

/* Matching
|Minimum Vertex Cover| = |Maximum Matching|
|Maximum Independent Set| = |V| - |Maximum Matching|
|Minimum Path Cover| = |V| - |Maximum Matching| (Directed Acyclic Graph)
|Minimum Edge Cover| = |V| - |Maximum Matching| / 2 (Undirected Graph)
 * warning: isolate vertex */
// O(|V|*|E|)
int n, m; // |V(x)|, |V(y)|
int mp[N][N], matx[N], maty[N]; bool fy[N];

int path(int u) {
  rep(v, m) if (mp[u][v] && !fy[v]) {
    fy[v] = 1;
    if (!~maty[v] || path(maty[v])) {
      matx[u] = v, maty[v] = u;
      return 1;
    }
  }
  return 0;
}
int hungary() {
  int ret = 0;
  clr(matx, 0xff), clr(maty, 0xff);
  rep(i, n) if (!~matx[i]) {
    clr(fy, 0);
    ret += path(i);
  }
  return ret;
}

Prim

int n; // |V|
int mp[N][N], ml[N]; bool vis[N];

int prim() {
  int ret(0); clr(vis, 0), clr(ml, 0x3f); ml[0] = 0;
  rep(i, n) {
    int id(-1);
    rep(j, n) if (!vis[j] && (!~id || ml[j] < ml[id])) id = j;
    vis[id] = 1, ret += ml[id];
    rep(j, n) if (!vis[j] && mp[j][id] < ml[j]) ml[j] = mp[j][id];
  }
  return ret;
}

ISAP

void addedge(int u, int v, int c, int r = 0) {
  e[idx].u = v, e[idx].c = c, e[idx].next = p[u], p[u] = idx++;
  e[idx].u = u, e[idx].c = r, e[idx].next = p[v], p[v] = idx++;
}
//* bfs in the beginning to accelerate (+5%)
int gap[N], lev[N], cur[N], pre[N];
int sap(int s, int t, int n) {
  clr(gap, 0), clr(lev, 0), memcpy(cur, p, sizeof p);
  int u, v, ret(0), step(inf), mi;
  gap[0] = n, u = pre[s] = s;
  while (lev[s] < n) { loop:
    for (int &i = cur[u]; ~i; i = e[i].next) {
      v = e[i].u;
      if (e[i].c && lev[u] == lev[v] + 1) {
        step = min(step, e[i].c);
        pre[v] = u;
        u = v;
        if (v == t) {
          while (v != s) {
            u = pre[v];
            e[cur[u]].c -= step;
            e[cur[u] ^ 1].c += step;
            v = u;
          }
          ret += step;
          step = inf;
        }
        goto loop;
      }
    }
    mi = n;
    for (int i = p[u]; ~i; i = e[i].next) {
      v = e[i].u;
      if (e[i].c && lev[v] < mi) {
        mi = lev[v];
        cur[u] = i;
      }
    }
    if (!--gap[lev[u]]) break;
    ++gap[lev[u] = mi + 1];
    u = pre[u];
  }
  return ret;
}

Dinic

int cur[N], lev[N], Q[N], pre[N], st[N];
bool bfs(int s, int t) {
  clr(lev, 0xff); lev[s] = 0, Q[0] = s;
  for (int l = 0, h = 1, u, v; l < h; ) {
    u = Q[l++]; if (u == t) break;
    for (int i = p[u]; ~i; i = e[i].next) {
      v = e[i].u;
      if (e[i].c > 0 && !~lev[v]) {
        lev[v] = lev[u] + 1;
        Q[h++] = v;
      }
    }
  }
  return lev[t] != -1;
}
int dfs(int s, int t) {
  int u, v, top = 0, ret = 0, step, pos;
  st[++top] = s;
  while (top) {
    u = st[top];
    if (u == t) {
      pos = 1;
      Rep(i, top - 1) if (e[pre[i]].c < e[pre[pos]].c) pos = i;
      ret += (step = e[pre[pos]].c);
      Rep(i, top - 1) e[pre[i]].c -= step, e[pre[i] ^ 1].c += step;
      u = st[top = pos];
    }
    for (int &i = cur[u]; ~i; i = e[i].next) {
      v = e[i].u;
      if (e[i].c && lev[u] < lev[v]) {
        pre[top] = i, st[++top] = u = v;
        break;
      }
    }
    if (!~cur[u]) lev[u] = -1, --top;
  }
  return ret;
}
int dinic(int s, int t) {
  int ret = 0, c;
  while (bfs(s, t)) {
    memcpy(cur, p, sizeof p);
    ret += dfs(s, t);
  }
  return ret;
}

MinCostMaxFlow

//addedge(u, v, cap,  cost);
//addedge(v, u,   0, -cost);
//*warning: no Negative-Cycle
struct SSP {
  int mc, mf;
  int pre[N][2], Q[N], dis[N]; bool vis[N];
  bool spfa(int s, int t) {
    clr(dis, 0x3f), clr(vis, 0); dis[s] = 0, Q[0] = s, vis[s] = 1;
    int u, v, w;
    for (int l = 0, h = 1; l != h; ) {
      vis[u = Q[l++]] = 0; if (l == N) l = 0;
      for (int i = p[u]; ~i; i = e[i].next) {
        v = e[i].u, w = e[i].f;
        if (e[i].c && dis[u] + w < dis[v]) {
          dis[v] = dis[u] + w;
          pre[v][0] = u, pre[v][1] = i;
          if (!vis[v]) {
            vis[v] = 1;
            Q[h++] = v; if (h == N) h = 0;
          }
        }
      }
    }
    return dis[t] != inf; // return dis[t] < 0: any flow
  }
  void solve(int s, int t) {
    mc = mf = 0; int u, step;
    while (spfa(s, t)) {
      step = inf;
      for (u = t; u != s; u = pre[u][0]) {
        step = min(step, e[pre[u][1]].c);
      }
      for (u = t; u != s; u = pre[u][0]) {
        e[pre[u][1]].c -= step;
        e[pre[u][1] ^ 1].c += step;
      }
      mf += step;
      mc += dis[t] * step;
    }
  }
};

MinCut(UndirectedGraph)

int v[N], mp[N][N], dis[N]; bool vis[N];
int Stoer_Wagner(int n) { // 0 ~ n-1
  int ret = inf, now, pre;
  rep(i, n) v[i] = i;
  while (n > 1) {
    now = 1, pre = 0;
    Rep(i, n - 1) {
      dis[v[i]] = mp[v[0]][v[i]];
      if (dis[v[i]] > dis[v[now]]) now = i;
    }
    clr(vis, 0), vis[v[0]] = 1;
    Rep(i, n - 2) {
      vis[v[now]] = 1, pre = now, now = -1;
      Rep(j, n - 1) if (!vis[v[j]]) {
        dis[v[j]] += mp[v[pre]][v[j]];
        if (now == -1 || dis[v[now]] < dis[v[j]]) now = j;
      }
    }
    ret = min(ret, dis[v[now]]);
    rep(i, n) {
      mp[v[pre]][v[i]] += mp[v[now]][v[i]];
      mp[v[i]][v[pre]] = mp[v[pre]][v[i]];
    }
    v[now] = v[--n];
  }
  return ret;
}