ACdream 1103 瑶瑶正式成为CEO(树链剖分+费用流)
Problem Description
瑶瑶(tsyao)是某知名货运公司(顺丰)的老板,这个公司很大,货物运输量极大,因此公司修建了许多交通设施,掌控了一个国家的交通运输。
这个国家有n座城市,公司的总部在1号城市。
公司下管辖的有m条道路和n-1段火车线路。
这m条道路和n-1条火车线路都可以用u来表示起点,v来表示终点(数据保证m条道路和n-1条火车线路构成有向无环图)。
这n-1段火车道保证从1号城市出发,能够有唯一的一道只包含火车道的线路到达其他n-1座城市。
每条道路和每段火车道都有一个最佳搭载货物值ai,如果要搭载的货物超过了ai,公司需要对经过该路线的超过ai的每单位货物增加bi的维修费用,由于种种原因,如果搭载的货物低于ai,公司需要对少的每单位货物(设该路线有x的货物,则计算为ai-x单位)增加ci的维修费用。当然,每单位货物经过时,会有di的基础维护费用。
这里有两种操作:
C xi yi zi: 随着时间和环境的变化,火车道会受到一些影响,xi到yi的火车道ai会改变zi(新的ai应该为ai+zi),若xi不能到达yi,则将hi到xi和hi到yi的路段ai改变zi(hi为可以到达xi和yi的城市,且不存在fi使得 hi能够到达fi,fi能够到达xi和yi)。
当某火车道的ai值小于0时,我们看做该条火车道的最佳搭载货物值为0(当然ai事实上是负数);
Q vi wi: 查询当计划将wi单位货物从1号城市到vi号城市时,该公司需要的最小维护费用。维护费用计算为每条道路和火车道的维护费用的和(SUMbi+SUMci+SUMdi)。
Input
第一行两个整数n,m,用空格隔开。
接下来n-1+m行,每行u,v,ai,bi,ci,di六个整数。
前n-1行表示火车线路,后m行表示道路。
接下来一行为一个整数q。
接下来q行分别为上述两种操作。
Output
对于每次Q操作,输出答案,数据保证答案在int范围内。
题目大意:略。
思路:
——————————————————————————————————————————————————————————————————
扒官方题解:http://tsyao.tk/archives/94
对付修改的话,就用树链剖分就好,然后每次询问跑网络流。
网络流这样建图,先假设我每条边都跑了0的流量,我们先算出跑了0的流量的费用,然后对于一条边,我跑了小于ai的流量的时候,每次增加一点流量,就相当于减小了ci的费用,所以把一条边拆成两条边,一条是费用为-ci+di,上界为ai的边,一条是费用为bi+di,上界为无穷的边。。。
——————————————————————————————————————————————————————————————————
PS:简单的说就是两条SB题合在一起出,这样也脱离不了它是SB题的结果。但是却忘了删一条调试语句导致无限TLE……
代码(1772MS):
- #include <cstdio>
- #include <iostream>
- #include <cstring>
- #include <algorithm>
- #include <queue>
- using namespace std;
- typedef long long LL;
- const int MAXN = ;
- const int MAXV = MAXN;
- const int MAXE = * ( * + MAXN * );
- const int MAXT = MAXN << ;
- const int INF = 0x3f3f3f3f;
- struct SPFA_COST_FLOW {
- int head[MAXV];
- int to[MAXE], next[MAXE], cap[MAXE], flow[MAXE];
- LL cost[MAXE];
- int n, m, ecnt, st, ed;
- void init(int n) {
- this->n = n;
- memset(head + , -, n * sizeof(int));
- ecnt = ;
- }
- void add_edge(int u, int v, int f, LL c) {
- to[ecnt] = v; cap[ecnt] = f; cost[ecnt] = c; next[ecnt] = head[u]; head[u] = ecnt++;
- to[ecnt] = u; cap[ecnt] = ; cost[ecnt] = -c; next[ecnt] = head[v]; head[v] = ecnt++;
- }
- void clear() {
- memset(flow, , ecnt * sizeof(int));
- }
- LL dis[MAXV];
- int pre[MAXV];
- bool vis[MAXV];
- bool spfa() {
- memset(vis + , , n * sizeof(bool));
- memset(dis, 0x3f, (n + ) * sizeof(LL));
- queue<int> que; que.push(st);
- dis[st] = ;
- while(!que.empty()) {
- int u = que.front(); que.pop();
- vis[u] = false;
- for(int p = head[u]; ~p; p = next[p]) {
- int v = to[p];
- if(cap[p] - flow[p] && dis[u] + cost[p] < dis[v]) {
- dis[v] = dis[u] + cost[p];
- pre[v] = p;
- if(!vis[v]) {
- que.push(v);
- vis[v] = true;
- }
- }
- }
- }
- return dis[ed] < dis[];
- }
- LL maxFlow, minCost;
- LL min_cost_flow(int ss, int tt) {
- st = ss, ed = tt;
- maxFlow = minCost = ;
- while(spfa()) {
- int u = ed, tmp = INF;
- while(u != st) {
- tmp = min(tmp, cap[pre[u]] - flow[pre[u]]);
- u = to[pre[u] ^ ];
- }
- u = ed;
- while(u != st) {
- flow[pre[u]] += tmp;
- flow[pre[u] ^ ] -= tmp;
- u = to[pre[u] ^ ];
- }
- maxFlow += tmp;
- minCost += tmp * dis[ed];
- }
- return minCost;
- }
- } G;
- struct Tree {
- struct Edge {
- int a, b, c, d, u, v;
- void read() {
- scanf("%d%d%d%d%d%d", &u, &v, &a, &b, &c, &d);
- }
- } tree[MAXN], edge[MAXE];
- int tid[MAXN], eid[MAXN], size[MAXN], son[MAXN], top[MAXN], dep[MAXN], fa[MAXN];
- int n, m, q;
- int head[MAXV], pre[MAXV], ecnt, dfs_clock;
- int to[MAXE], next[MAXE], id[MAXE];
- LL add[MAXT];
- void init() {
- memset(head + , -, n * sizeof(int));
- ecnt = dfs_clock = ;
- }
- void add_edge(int u, int v, int i) {
- to[ecnt] = v; id[ecnt] = i; next[ecnt] = head[u]; head[u] = ecnt++;
- to[ecnt] = u; id[ecnt] = i; next[ecnt] = head[v]; head[v] = ecnt++;
- }
- void dfs_size(int u, int f, int depth) {
- size[u] = ; dep[u] = depth; fa[u] = f;
- int maxsize = son[u] = ;
- for(int p = head[u]; ~p; p = next[p]) {
- int v = to[p];
- if(v == f) continue;
- pre[v] = p;
- dfs_size(v, u, depth + );
- size[u] += size[v];
- if(size[v] > maxsize) {
- maxsize = size[v];
- son[u] = v;
- }
- }
- }
- void dfs_heavy_edge(int u, int ancestor) {
- tid[u] = ++dfs_clock; eid[dfs_clock] = id[pre[u]];
- top[u] = ancestor;
- if(son[u]) dfs_heavy_edge(son[u], ancestor);
- for(int p = head[u]; ~p; p = next[p]) {
- int v = to[p];
- if(v == fa[u] || v == son[u]) continue;
- dfs_heavy_edge(v, v);
- }
- }
- #define ll (x << 1)
- #define rr (ll | 1)
- #define mid ((l + r) >> 1)
- void pushdown(int x) {
- if(add[x]) {
- add[ll] += add[x];
- add[rr] += add[x];
- add[x] = ;
- }
- }
- void pushadd(int x, int l, int r) {
- if(l == r) {
- if(l > ) tree[eid[l]].a += add[x];
- add[x] = ;
- } else {
- pushdown(x);
- pushadd(ll, l, mid);
- pushadd(rr, mid + , r);
- }
- }
- void modify(int x, int l, int r, int a, int b, int val) {
- if(a <= l && r <= b) {
- add[x] += val;
- } else {
- if(a <= mid) modify(ll, l, mid, a, b, val);
- if(mid < b) modify(rr, mid + , r, a, b, val);
- }
- }
- void modify(int x, int y, int val) {
- while(top[x] != top[y]) {
- if(dep[top[x]] < dep[top[y]]) swap(x, y);
- modify(, , n, tid[top[x]], tid[x], val);
- x = fa[top[x]];
- }
- if(x != y) {
- if(dep[x] < dep[y]) swap(x, y);
- modify(, , n, tid[son[y]], tid[x], val);
- }
- }
- int gid[MAXV];
- void initQuery() {
- G.init(n + );
- for(int i = ; i < n; ++i) {
- Edge &t = tree[i];
- gid[i] = G.ecnt;
- G.add_edge(t.u, t.v, max(, t.a), t.d - t.c);
- G.add_edge(t.u, t.v, INF, t.d + t.b);
- }
- for(int i = ; i < m; ++i) {
- Edge &t = edge[i];
- G.add_edge(t.u, t.v, max(, t.a), t.d - t.c);
- G.add_edge(t.u, t.v, INF, t.d + t.b);
- }
- G.add_edge(n + , , , );
- }
- int query(int tt, int val) {
- int ss = n + ;
- pushadd(, , n);
- LL sum = ;
- for(int i = ; i < n; ++i) {
- Edge &t = tree[i];
- sum += t.c * max(, t.a);
- G.cap[gid[i]] = max(, t.a);
- }
- for(int i = ; i < m; ++i) {
- Edge &t = edge[i];
- sum += t.c * max(, t.a);
- }
- G.cap[G.ecnt - ] = val;
- G.clear();
- return sum + G.min_cost_flow(ss, tt);
- }
- void work() {
- scanf("%d%d", &n, &m);
- for(int i = ; i < n; ++i) tree[i].read();
- for(int i = ; i < m; ++i) edge[i].read();
- init();
- initQuery();
- for(int i = ; i < n; ++i) add_edge(tree[i].u, tree[i].v, i);
- dfs_size(, , );
- dfs_heavy_edge(, );
- scanf("%d", &q);
- char op;
- for(int i = , a, b, c; i < q; ++i) {
- scanf(" %c", &op);
- if(op == 'Q') {
- scanf("%d%d", &a, &b);
- printf("%d\n", query(a, b));
- } else {
- scanf("%d%d%d", &a, &b, &c);
- modify(a, b, c);
- }
- }
- }
- } T;
- int main() {
- T.work();
- }
ACdream 1103 瑶瑶正式成为CEO(树链剖分+费用流)的更多相关文章
- BZOJ 1103: [POI2007]大都市meg( 树链剖分 )
早上数学考挂了...欲哭无泪啊下午去写半个小时政治然后就又可以来刷题了.. 树链剖分 , 为什么跑得这么慢... ------------------------------------------- ...
- 1103. [POI2007]MEG-Megalopolis【树链剖分】
Description 在经济全球化浪潮的影响下,习惯于漫步在清晨的乡间小路的邮递员Blue Mary也开始骑着摩托车传递邮件了. 不过,她经常回忆起以前在乡间漫步的情景.昔日,乡下有依次编号为1.. ...
- HDU 5452——Minimum Cut——————【树链剖分+差分前缀和】ACdream 1429——Diversion——————【树链剖分】
Minimum Cut Time Limit: 3000/2000 MS (Java/Others) Memory Limit: 65535/102400 K (Java/Others)Tota ...
- BZOJ 2157: 旅游( 树链剖分 )
树链剖分.. 样例太大了根本没法调...顺便把数据生成器放上来 -------------------------------------------------------------------- ...
- BZOJ 3626: [LNOI2014]LCA [树链剖分 离线|主席树]
3626: [LNOI2014]LCA Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 2050 Solved: 817[Submit][Status ...
- BZOJ 1984: 月下“毛景树” [树链剖分 边权]
1984: 月下“毛景树” Time Limit: 20 Sec Memory Limit: 64 MBSubmit: 1728 Solved: 531[Submit][Status][Discu ...
- codevs 1228 苹果树 树链剖分讲解
题目:codevs 1228 苹果树 链接:http://codevs.cn/problem/1228/ 看了这么多树链剖分的解释,几个小时后总算把树链剖分弄懂了. 树链剖分的功能:快速修改,查询树上 ...
- 并查集+树链剖分+线段树 HDOJ 5458 Stability(稳定性)
题目链接 题意: 有n个点m条边的无向图,有环还有重边,a到b的稳定性的定义是有多少条边,单独删去会使a和b不连通.有两种操作: 1. 删去a到b的一条边 2. 询问a到b的稳定性 思路: 首先删边考 ...
- 树链剖分+线段树 CF 593D Happy Tree Party(快乐树聚会)
题目链接 题意: 有n个点的一棵树,两种操作: 1. a到b的路径上,给一个y,对于路径上每一条边,进行操作,问最后的y: 2. 修改某个条边p的值为c 思路: 链上操作的问题,想树链剖分和LCT,对 ...
随机推荐
- filter:Alpha总结
filter:Alpha(Opacity=?, FinishOpacity=?, Style=?, StartX=?, StartY=?, FinishX=?, FinishY=?)Opacity:透 ...
- SQL Server游标【转】
什么是游标 结果集,结果集就是select查询之后返回的所有行数据的集合. 游标则是处理结果集的一种机制吧,它可以定位到结果集中的某一行,多数据进行读写,也可以移动游标定位到你所需要的行中进行操作 ...
- 抓包工具Charles 【转】
今天就来看一下Mac上如何进行抓包,之前有一篇文章介绍了使用Fidder进行抓包 http://blog.csdn.net/jiangwei0910410003/article/details/1 ...
- 已禁用对分布式事务管理器(MSDTC)的网络访问。请使用组件服务管理工具启用 DTC 以便在 MSDTC 安全配置中进行网络访问。
今天写ASP.NET程序,在网页后台的c#代码里写了个事务,事务内部对一张表进行批量插入,对另外一张表进行查询与批量插入. 结果第二张表查询后foreach迭代操作时报错:已禁用对分布式事务管理器(M ...
- nginx常用变量
$args, 请求中的参数; $content_length, HTTP请求信息里的”Content-Length”; $content_type, 请求信息里的”Content-Type”; $do ...
- 【Android测试】【第十一节】Uiautomator——简介
◆版权声明:本文出自胖喵~的博客,转载必须注明出处. 转载请注明出处:http://www.cnblogs.com/by-dream/p/4872244.html 前言 在App的测试中,除了单元测试 ...
- 超级管理员登录后如果连续XX分钟没有操作再次操作需要重新登录
首先在设置session页面时 session_start(); session("name",$adminname); //加入session时间 time() session( ...
- js保留n位小数
1.功能:将浮点数四舍五入,取小数点后2位 function toDecimal(num) { var f = parseFloat(num); if (isNaN(f)) { return; } f ...
- 关于actionscript中新建一个sprite,设置大小(宽高)的问题。
有一定as3开发经验的童鞋应该知道,新建一个sprite,是无法设置大小的,即时设置了,也不会生效,宽高还是为0,据说反而有副作用(http://www.cnblogs.com/yjmyzz/arch ...
- 给ul中的li添加事件的多种方法
给ul中的li添加事件的多种方法 这是一个常见,而且典型的前端面试题 <ul> <li>11111</li> <li>22222</li> ...