Given a connected undirected graph G = (V, E) with positive right of the Side Band, where n = | v |, M = | E |, n vertices are sequentially numbered from 1 to n, and three positive integers U, V, and L (U =v) are given. Suppose we add an edge with the Edge Weight of L (u, v), so we need to delete the minimum number of edges so that this edge may appear on the least-generated tree or the maximum-generated tree?
Idea: For an edge, if a part of all the edges smaller than the edge weight is used, the two endpoints of the edge can be connected, this edge will not appear in the minimal spanning tree. The maximum spanning tree is the same.
It is equivalent to finding the least deleted edge, so that the edge smaller than the edge weight cannot connect the two endpoints, And the edge greater than the edge weight cannot connect the two endpoints.
Therefore, you can create a graph to obtain the minimum cut.
Code:
#include <queue>#include <cstdio>#include <cstring>#include <climits>#include <iostream>#include <algorithm>using namespace std; #define N 20010#define M 200010struct Edge { int f, t, len; void read() { scanf("%d%d%d", &f, &t, &len); }}E[M]; #define INF 0x3f3f3f3fqueue<int> q;struct Solver { int head[N], next[M << 1], end[M << 1], flow[M << 1], ind; int d[N], gap[N], stack[N], top, cur[N]; void reset() { ind = top = 0; memset(head, -1, sizeof head); } void addedge(int a, int b, int _flow) { int q = ind++; end[q] = b; next[q] = head[a]; head[a] = q; flow[q] = _flow; } void addedge_db(int a, int b, int _flow) { addedge(a, b, _flow); addedge(b, a, _flow); } void make(int a, int b, int _flow) { addedge(a, b, _flow); addedge(b, a, 0); } void bfs(int T) { memset(d, -1, sizeof d); memset(gap, 0, sizeof gap); ++gap[d[T] = 0]; int i, j; q.push(T); while(!q.empty()) { i = q.front(); q.pop(); for(j = head[i]; j != -1; j = next[j]) if (d[end[j]] == -1) ++gap[d[end[j]] = d[i] + 1], q.push(end[j]); } } int Maxflow(int S, int T) { int Min, ins, res = 0; memcpy(cur, head, sizeof(cur)); bfs(T); int u = S; while(d[S] < (T - S + 1)) { if (u == T) { Min = INF; for(int i = 0; i < top; ++i) if (flow[stack[i]] < Min) Min = flow[stack[i]], ins = i; for(int i = 0; i < top; ++i) { flow[stack[i]] -= Min; flow[stack[i] ^ 1] += Min; } res += Min; u = end[stack[top = ins] ^ 1]; } if (u != T && !gap[d[u] - 1]) break; bool find = 0; for(int &j = cur[u]; j != -1; j = next[j]) if (flow[j] && d[end[j]] + 1 == d[u]) { find = 1; ins = j; break; } if (find) { stack[top++] = ins; cur[u] = ins; u = end[ins]; } else { Min = T - S + 1; for(int j = head[u]; j != -1; j = next[j]) { if (flow[j] && d[end[j]] < Min) { Min = d[end[j]]; cur[u] = j; } } if (!--gap[d[u]]) break; ++gap[d[u] = Min + 1]; if (u != S) u = end[stack[--top] ^ 1]; } } return res; }}G; int main() { int n, m; scanf("%d%d", &n, &m); register int i, j; for(i = 1; i <= m; ++i) E[i].read(); int u, v, L; scanf("%d%d%d", &u, &v, &L); int tot = 0; G.reset(); G.make(0, u, INF); G.make(v, n + 1, INF); for(i = 1; i <= m; ++i) if (E[i].len < L) G.addedge_db(E[i].f, E[i].t, 1); tot += G.Maxflow(0, n + 1); G.reset(); G.make(0, u, INF); G.make(v, n + 1, INF); for(i = 1; i <= m; ++i) if (E[i].len > L) G.addedge_db(E[i].f, E[i].t, 1); tot += G.Maxflow(0, n + 1); printf("%d", tot); return 0;}
Bzoj2561 minimal spanning tree