题目:
n个用户上网,有m条网线。每条网线规定只[L,R]区间中的用户能上,且最多同时上v人。问最多能同时几人在线。
组数不超过10
n,m(1<=n,m<=10000)
做法:
看这个题面,第一时间想到最大流。当然看到数据范围发现有点勉强。(但跑得还挺快)
考虑朴素的建图:
1、源点s和每个用户建边,流量1;
2、每个用户和能连上的网线建边,流量1;
3、每条网线和汇点t建边,流量v。
但是这样边数就太多了。想想,每条网线都要连R-L+1条边其实是没必要,考虑可以用线段树维护整段区间建边,这样可以减少很多的边。
然后用sap跑最大流。
代码:
#include <bits/stdc++.h>
#define lson rt<<1
#define rson rt<<1|1
#define IOS ios::sync_with_stdio(false), cin.tie(0)
#define debug(a) cout << #a ": " << a << endl
using namespace std;
typedef long long ll;
inline int read(void){
char ch = getchar();
int ans = 0;
while (!isdigit(ch)) ch = getchar();
while (isdigit(ch)) ans = ans*10 + ch-'0', ch = getchar();
return ans;
}
const int N = 7e4 + 7;
const int M = 2e6 + 7;
const int inf = 0x3f3f3f3f;
int n, m;
struct edge{
int v, cap, nxt;
}e[M];
int tot, head[N];
int tag, T[N<<2];
int dep[N], gap[N], q[M], stk[M], top, tail, cur[N];
void init(void){
tot = 0; memset(head, -1, sizeof head);
}
void addedge(int u, int v, int f){
e[tot] = (edge){v, f, head[u]}; head[u] = tot++;
e[tot] = (edge){u, 0, head[v]}; head[v] = tot++;
}
void build(int l, int r, int rt){
T[rt] = ++tag;
if (l == r){
addedge(0, T[rt], 1);
return;
}
int mid = (l+r) >> 1;
build(l, mid, lson); build(mid+1, r, rson);
addedge(T[lson], T[rt], mid-l+1);
addedge(T[rson], T[rt], r-mid);
}
void update(int L, int R, int p, int l, int r, int rt){
if (L <= l && r <= R){
addedge(T[rt], p, r-l+1); return;
}
int mid = (l+r) >> 1;
if (L <= mid) update(L, R, p, l, mid, lson);
if (R > mid) update(L, R, p, mid+1, r, rson);
}
void bfs(int s, int t){
top = tail = 0;
for (int i = s; i <= t; ++i){
dep[i] = -1, gap[i] = 0;
}
gap[0] = 1;
dep[t] = 0;
q[tail++] = t;
while (top != tail){
int u = q[top++];
for (int i = head[u]; i != -1; i = e[i].nxt){
int v = e[i].v;
if (dep[v] == -1){
dep[v] = dep[u]+1;
gap[dep[v]]++;
q[tail++] = v;
}
}
}
}
int sap(int s, int t, int N){
bfs(s, t);
for (int i = s; i <= t; ++i) cur[i] = head[i];
top = 0;
int u = s;
int ans = 0;
while (dep[s] < N){
if (u == t){
int mn = inf;
int inser;
for (int i = 0; i < top; ++i){
if (mn > e[stk[i]].cap){
mn = e[stk[i]].cap;
inser = i;
}
}
for (int i = 0; i < top; ++i){
e[stk[i]].cap -= mn;
e[stk[i]^1].cap += mn;
}
ans += mn;
top = inser;
u = e[stk[top]^1].v;
continue;
}
bool flag = false;
int v;
for (int i = cur[u]; i != -1; i = e[i].nxt){
v = e[i].v;
if (e[i].cap && dep[v]+1 == dep[u]){
flag = true;
cur[u] = i;
break;
}
}
if (flag){
stk[top++] = cur[u];
u = v;
continue;
}
int mn = N;
for (int i = head[u]; i != -1; i = e[i].nxt){
if (e[i].cap && dep[e[i].v] < mn){
mn = dep[e[i].v];
cur[u] = i;
}
}
gap[dep[u]]--;
if (!gap[dep[u]]) return ans;
dep[u] = mn + 1;
gap[dep[u]]++;
if (u != s) u = e[stk[--top]^1].v;
}
return ans;
}
int main(void){
while (scanf("%d%d", &n, &m) != EOF){
init();
tag = 0; build(1, n, 1);
int s = 0, t = tag+m+1;
for (int i = 1; i <= m; ++i){
int l = read(), r = read(), v = read();
update(l, r, tag+i, 1, n, 1);
addedge(tag+i, t, v);
}
printf("%d\n", sap(s, t, t+1));
}
return 0;
}
京公网安备 11010502036488号