Acdream1103 瑶瑶正式成为CEO(费用流+树剖)
来源:互联网 发布:hp网络打印机m701 编辑:程序博客网 时间:2024/04/29 20:30
题目链接
中文题意就略去。求1到u的最小费用可以用费用流来做,其他的就直接遍历一遍。那么铁路的a值的更改需要用树剖来维护,
并且每次查询前需要把线断树中的a值更新到tree,再重新构网络流的图跑费用流。先算出流量为0时的费用sum=∑ci ,
然后对于每单位流量,相当于其经过的边要少花c,当流量超过了a时就不能相当于少花了,所以这里需要拆边,分为流量小于等于
a和大于a,费用分别为d - c和d + b。
/*****************************************Author :Crazy_AC(JamesQi)Time :2016/08/27File Name :*****************************************/// #pragma comment(linker, "/STACK:1024000000,1024000000")#include <iostream>#include <algorithm>#include <iomanip>#include <sstream>#include <string>#include <stack>#include <queue>#include <deque>#include <vector>#include <map>#include <set>#include <cstdio>#include <cstring>#include <cmath>#include <cstdlib>#include <climits>using namespace std;#define lson rt << 1#define rson rt << 1 | 1typedef long long LL;const int INF = 0x3f3f3f3f;const int maxn = 510;const int maxm = 4*(1000 + 2000 + 12);struct MinCostMaxFlow { int head[maxn], pnt[maxm], cap[maxm], flow[maxm], nxt[maxm], ecnt; LL cost[maxm]; void init() { memset(head, -1, sizeof head), ecnt = 0; } inline void addedge(int u,int v,int cp, LL co) { pnt[ecnt] = v, cap[ecnt] = cp, cost[ecnt] = co, nxt[ecnt] = head[u], head[u] = ecnt++; pnt[ecnt] = u, cap[ecnt] = 0, cost[ecnt] = -co, nxt[ecnt] = head[v], head[v] = ecnt++; } inline void clear() { memset(flow, 0, sizeof flow); } int pre[maxn], dis[maxn]; bool vis[maxn]; bool spfa(int s,int t) { memset(dis, INF, sizeof dis); queue<int> que; que.push(s); dis[s] = 0; while(!que.empty()) { int u = que.front();que.pop();vis[u] = false; for (int i = head[u];~i;i = nxt[i]) { int v = pnt[i]; if (cap[i] > flow[i] && dis[v] > dis[u] + cost[i]) { dis[v] = dis[u] + cost[i]; pre[v] = i; if (!vis[v]) {vis[v] = true;que.push(v);} } } } return dis[t] != INF; } LL MCMF(int s, int t) { LL MinCost = 0; while(spfa(s, t)) { int ang = INF; for (int u = t;u != s;u = pnt[pre[u] ^ 1]) ang = min(ang, cap[pre[u]] - flow[pre[u]]); for (int u = t;u != s;u = pnt[pre[u] ^ 1]) { flow[pre[u]] += ang; flow[pre[u] ^ 1] += ang; } MinCost += (LL)dis[t] * ang; } return MinCost; }}G;struct Edge { int u, v, a, b, c, d; void read() { scanf("%d%d%d%d%d%d", &u, &v, &a, &b, &c, &d); }}tree[maxn], edge[maxm];int idx[maxm], pre[maxm];int eid[maxm];struct Solve { int n, m; int head[maxn], pnt[maxn*2], nxt[maxn*2], ecnt; int Hash[maxm]; int dep[maxn], size[maxn], son[maxn], fa[maxn], top[maxn], SegId[maxn], tot; void init() { memset(head, -1, sizeof head), ecnt = tot = 0; } inline void addedge(int u, int v,int i) { pnt[ecnt] = v, idx[ecnt] = i, nxt[ecnt] = head[u], head[u] = ecnt++; pnt[ecnt] = u, idx[ecnt] = i, nxt[ecnt] = head[v], head[v] = ecnt++; } struct Segment { struct node { int l, r, add; node() {} node(int l, int r, int add) : l(l), r(r), add(add) {} }p[maxn<<2]; void build(int rt,int l, int r) { p[rt] = node(l, r, 0); if (l == r) return ; int mid = (l + r) >> 1; build(lson, l, mid); build(rson, mid + 1, r); } void pushdown(int rt) { if (p[rt].add != 0) { p[lson].add += p[rt].add; p[rson].add += p[rt].add; p[rt].add = 0; } } void updata(int rt,int l, int r, int val) { if (l <= p[rt].l && p[rt].r <= r) { p[rt].add += val; return ; } int mid = (p[rt].l + p[rt].r) >> 1; if (l <= mid) updata(lson, l, r, val); if (r > mid) updata(rson, l, r, val); } //把线断树上的变化值更新到tree上去 void push(int rt) { if (p[rt].l == p[rt].r) { if (p[rt].l > 1) tree[eid[p[rt].l]].a += p[rt].add; p[rt].add = 0; return ; } pushdown(rt); push(lson); push(rson); } }ST; void dfs_first(int u,int f,int depth) { fa[u] = f, size[u] = 1, son[u] = -1, dep[u] = depth; int maxSize = 0; for (int i = head[u];~i;i = nxt[i]) { int v = pnt[i]; if (v == f) continue; pre[v] = i; dfs_first(v, u, depth + 1); size[u] += size[v]; if (size[v] > maxSize) { maxSize = size[v], son[u] = v; } } } void dfs_second(int u,int header) { SegId[u] = ++tot;top[u] = header; eid[tot] = idx[pre[u]]; if (son[u] == -1) return ; if (son[u] != -1) dfs_second(son[u], header); for (int i = head[u];~i;i = nxt[i]) { if (pnt[i] != fa[u] && pnt[i] != son[u]) dfs_second(pnt[i], pnt[i]); } } /*初始化流量图*/ inline void InitG() { G.init(); for (int i = 1;i < n;++i) { /*纪录每条tree边添加到流量图中的正向边的编号*/ Hash[i] = G.ecnt; Edge& e = tree[i]; G.addedge(e.u, e.v, max(e.a, 0), e.d - e.c); G.addedge(e.u, e.v, INF, e.d + e.b); } for (int i = 1;i <= m;++i) { Edge& e = edge[i]; G.addedge(e.u, e.v, max(e.a, 0), e.d - e.c); G.addedge(e.u, e.v, INF, e.d + e.b); } /*vs = n + 1*/ G.addedge(n + 1, 1, 0, 0); } LL Query(int u, int val) { ST.push(1);/*更新tree中的a值*/ LL sum = 0; for (int i = 1;i < n;++i) { /*重新更替流量图中的cap值*/ G.cap[Hash[i]] = max(0, tree[i].a); sum += (LL)max(0, tree[i].a) * (LL)tree[i].c; } for (int i = 1;i <= m;++i) sum += (LL)max(0, edge[i].a) * (LL)edge[i].c; /*汇点出来的流量*/ G.cap[G.ecnt - 2] = val; G.clear(); return sum + G.MCMF(n + 1, u); } /*树剖维护tree中a值的变化值*/ void modify(int u,int v,int val) { int p = top[u], q = top[v]; while(p != q) { if (dep[p] < dep[q]) { swap(p, q); swap(u, v); } ST.updata(1, SegId[p], SegId[u], val); u = fa[p]; p = top[u]; } if (u != v) { if (dep[u] < dep[v]) swap(u, v); ST.updata(1, SegId[v] + 1, SegId[u], val); } } inline void work() { scanf("%d%d", &n, &m); init(); /*添加本地tree*/ for (int i = 1;i < n;++i) { tree[i].read(); addedge(tree[i].u, tree[i].v, i); } for (int i = 1;i <= m;++i) edge[i].read(); /*初始化流量图*/ InitG(); /*初始化线断树*/ ST.build(1, 1, n); dfs_first(1, -1, 0); dfs_second(1, 1); int Q;cin >> Q; while(Q--) { char op[5]; scanf("%s", op); if (op[0] == 'Q') { int a, b; scanf("%d%d", &a, &b); printf("%lld\n", Query(a, b)); }else { int a, b, c; scanf("%d%d%d", &a, &b, &c); modify(a, b, c); } } }}gao;int main(int argc, const char * argv[]){ // freopen("in.txt","r",stdin); // freopen("out.txt","w",stdout); // ios::sync_with_stdio(false); // cout.sync_with_stdio(false); // cin.sync_with_stdio(false); gao.work(); // showtime; return 0;}
0 0
- Acdream1103 瑶瑶正式成为CEO(费用流+树剖)
- 【ACdream】1103 瑶瑶正式成为CEO 树链剖分+费用流
- ACdream 1103 瑶瑶正式成为CEO (树链剖分+最小费用最大流)
- 如何才能成为一个CEO
- 正式成为博客一族
- XQuery正式成为标准
- 正式成为ABAPer
- 正式成为CSDN会员了
- 正式成为北漂一族
- 正式成为CSDN博客专家
- 如果乔布斯成为Google首任CEO
- 怎样成为一个称职的创业CEO
- 如何成为一位优秀的创业CEO
- 如何成为一位优秀的创业CEO
- 如何成为一位优秀的创业CEO
- 如何成为一位优秀的创业CEO
- 求伯君70万年薪正式出任金山CEO
- 微软宣布正式任命纳德拉为微软新任CEO
- HDFS文件权限及ACL访问控制
- MFC基于CPlex结构的内存池化管理
- POJ 3044单调栈
- Tomcat 8.x 从WebDotXml中的Servlet标签 -> Servlet的包装器StandardWrapper ->管道链末尾实例化Servlet对象
- 键盘的一些状态的改变
- Acdream1103 瑶瑶正式成为CEO(费用流+树剖)
- 关于学习
- yum 安装php56w
- BZOJ 4557 [JLoi2016]侦察守卫
- 前端将json数据解析成js对象失败
- lighttpd 服务器搭建过程记录
- HashSet简单用法
- JAV基础————对集合的简单理解
- Linux驱动开发-混杂字符设备驱动模型笔记 4