首页 > 代码库 > BZOJ2561 最小生成树
BZOJ2561 最小生成树
题目大意:给定一个边带正权的连通无向图G=(V,E),其中N=|V|,M=|E|,N个点从1到N依次编号,给定三个正整数u,v,和L (u≠v),假设现在加入一条边权为L的边(u,v),那么需要删掉最少多少条边,才能够使得这条边既可能出现在最小生成树上,也可能出现在最大生成树上?
思路:对于某一条边,如果用小于这条边边权的所有边中的一部分就能够使得这条边的两个端点连通,那么这一条边必然不会出现在最小生成树中。最大生成树同理。
那么等价于求出删除最少的边,使得小于该边权的边不能使得两个端点连通,大于该边权的边也不能使得两个端点连通。
于是分别建图求最小割即可。
Code:
#include <queue> #include <cstdio> #include <cstring> #include <climits> #include <iostream> #include <algorithm> using namespace std; #define N 20010 #define M 200010 struct Edge { int f, t, len; void read() { scanf("%d%d%d", &f, &t, &len); } }E[M]; #define INF 0x3f3f3f3f queue<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 最小生成树
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。