列表

详情


NC22615. 小y的工资

描述

给出一个城市的交通网络,该城市共有n个地点。共有n-1条有向道路,1号节点为关键节点。保证从关键节点出发可以到达任何一个节点。而且市长为了奖励那些离开关键城市,来减轻关键城市压力的人。每个沿着有向道路i的方向走的人都会获得w_i的收益。但是如果你足够有钱,你也可以强行逆行。但是这样会花费c_i的罚款。对于一条道路如果你已经得到过一次奖励那么不会再得到奖励。同样的,如果你已经在这条道路上被罚过一次款了,那么你不会在被罚第二次。
现在你要从你工作的S地点到你的家T地点。因为今年没挣到钱,所以你希望在回家途中可以得到尽可能多的money。现在你需要告诉你父母你今年挣到了多少钱。所以你需要多次回答从S到T你总共可以赚到多少¥。
由于种种原因,你要保证可以到达的情况下尽可能的离关键城市远。
如果你没有看懂上面的题意,请看简化版题意:
给出一棵以1号节点为根的树,对于第i条边,从父亲走向儿子会得到w_i的收益,从儿子走向父亲会付出c_i的代价。每次询问从S到T最多的收益是多少。
注意:在保证可以到达的情况下,要尽可能使路径上距离1号点最近的点与1号点之间的距离最远!!!而且此路径不一定是简单路径。
答案可能会是负收益

输入描述

第一行两个个正整数n,Q,表示一共有n个节点总共有Q次询问。
下面n-1行每行4个整数u,v,w,c,表示u,v之间有一条边(注意uv并不代表方向),顺行会得到w的收益,逆行会被罚款c。
然后Q行,每行两个正整数S,T。询问从S到T最多收益是多少。

输出描述

输出共Q行,第i行表示第i次询问的答案。

示例1

输入:

7 1
2 1 4 9
3 1 9 1
4 1 0 7
5 3 7 2
6 4 6 2
7 4 5 2
4 6

输出:

9

说明:

方案如下

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++14(g++5.4) 解法, 执行用时: 329ms, 内存消耗: 40644K, 提交时间: 2019-04-20 15:58:51

#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int MAXN = 1e5 + 10;
int n, q;
int f[MAXN][20], dep[MAXN];
ll sum1[MAXN], sum2[MAXN], ans;
ll dp[MAXN], dp2[MAXN], h[MAXN][20];
ll sch[MAXN];

struct edge { int to, w, c; };
vector<edge> e[MAXN];

void dfs(int p) {
	dep[p] = dep[f[p][0]] + 1;
	for (int i = 1; i < 20; ++i) f[p][i] = f[f[p][i - 1]][i - 1];
	for (auto c : e[p]) {
		if (c.to == f[p][0])continue;
		f[c.to][0] = p;
		sum1[c.to] = sum1[p] + c.w;
		sum2[c.to] = sum2[p] + c.w - c.c;
		dp[c.to] = c.w - c.c;
		dfs(c.to);
		dp[p] += dp[c.to];
		sch[p] += dp[c.to];
	}
	dp[p] = max<ll>(dp[p], 0);
}

void dfs2(int p) {
	ll su = 0;
	h[p][0] = dp2[p];
	for (int i = 1; i < 20; ++i)
		h[p][i] = h[p][i - 1] + h[f[p][i - 1]][i - 1];
	for (auto c : e[p]) {
		if (c.to == f[p][0])continue;
		su += dp[c.to];
	}
	for (auto c : e[p]) {
		if (c.to == f[p][0])continue;
		dp2[c.to] = su - dp[c.to];
		dfs2(c.to);
	}
}

int lca(int x, int y) {
	if (dep[x] < dep[y]) swap(x, y);
	for (int i = 19, t = dep[x] - dep[y]; i >= 0; i--)
		if (t >> i & 1) x = f[x][i];
	if (x == y) return x;
	for (int i = 19; i >= 0; --i)
		if (f[x][i] != f[y][i]) {
			x = f[x][i]; y = f[y][i];
		}
	return f[x][0];
}

int jump(int x, int y) {
	for (int i = 19; i >= 0; --i)
		if (dep[f[x][i]] > dep[y]) {
			ans += h[x][i];
			x = f[x][i];
		}
	return x;
}

int main() {
	scanf("%d%d", &n, &q);
	for (int i = 1; i < n; ++i) {
		int l, r, w, c;
		scanf("%d%d%d%d", &l, &r, &w, &c);
		e[l].push_back({ r, w, c });
		e[r].push_back({ l, w, c });
	}
	dfs(1);
	dfs2(1);
	while (q--) {
		int x, y; scanf("%d%d", &x, &y);
		if (x == y) {
			printf("%lld\n", sch[x]); continue;
		}
		int o = lca(x, y);
		ans = sum2[x] - sum2[o] + sum1[y] - sum1[o];
		int px = jump(x, o);
		int py = jump(y, o);
		ans += sch[o];
		if (px != o) {
			ans -= dp[px];
			ans += sch[x];
		}
		if (py != o) {
			ans -= dp[py];
			ans += sch[y];
		}
		printf("%lld\n", ans);
	}
}

C++11(clang++ 3.9) 解法, 执行用时: 484ms, 内存消耗: 45000K, 提交时间: 2019-04-19 21:45:06

#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
const int _=1e5+5;
ll n,Q,f[_],g[_],st[18][_],A[18][_],fz[_],gz[_],dep[_],ans;
struct edge{int v,w,c;};
vector<edge>e[_];
void dfs(int fa,int u){
	for(edge p:e[u]){
		int v=p.v;if(v==fa)continue;
		g[v]=p.w-p.c;
		fz[v]=fz[u]+p.w; gz[v]=gz[u]+p.c;
		dfs(u,v); f[u]+=g[v];
	}
	g[u]=max(0ll,g[u]+f[u]);
}
void Dfs(int fa,int u){
	st[0][u]=fa; A[0][u]=f[fa]-g[u]; dep[u]=dep[fa]+1;
	for(edge p:e[u]){
		int v=p.v;if(v==fa)continue;
		Dfs(u,v);
	}
}
void init(){
	for(int i=1;i<=17;++i)
		for(int j=1;j<=n;++j){
			st[i][j]=st[i-1][st[i-1][j]];
			A[i][j]=A[i-1][j]+A[i-1][st[i-1][j]];
		}
}
int lca(int x,int y){
	if(dep[x]<dep[y])swap(x,y);
	for(int i=17;~i;--i)
		if(dep[st[i][x]]>=dep[y])
			ans+=A[i][x],x=st[i][x];
	if(x==y)return x;
	for(int i=17;~i;--i)
		if(st[i][x]!=st[i][y]){
			ans+=A[i][x]+A[i][y];
			x=st[i][x],y=st[i][y];
		}
	ans+=A[0][x]+A[0][y];
	return st[0][x];
}
int main(){
	ios::sync_with_stdio(false);
	cin>>n>>Q;
	for(int i=1;i<n;++i){
		int u,v,w,c;cin>>u>>v>>w>>c;
		e[u].push_back((edge){v,w,c});
		e[v].push_back((edge){u,w,c});
	}
	dfs(0,1);Dfs(0,1); init();
	while(Q--){
		int u,v,x;cin>>u>>v;ans=0; x=lca(u,v);
		cout<<ans+f[u]+f[v]+(fz[u]+fz[v]-fz[x]*2)-f[x]-(gz[u]-gz[x])<<endl;
	}
}

上一题