Igallta【博弈论】【DP】

>Link

luogu T207970


>Description

在这里插入图片描述
n ≤ 2 ∗ 1 0 5 , m ≤ 5 ∗ 1 0 5 n\le 2*10^5, m\le5*10^5 n2105,m5105

idea:stoorz


>解题思路

考虑当前在 u u u 点,对于A / B当前选的路 ( u , v ) (u,v) (u,v)是否最优,那就要想 ( u , v ) (u,v) (u,v)对答案的贡献,和 v v v 点之后对答案的贡献是否最优,也就是要想之后的环境是否有利于A / B
我们发现这很难搞(所以我就不会做了QwQ)
既然要考虑之后的贡献,那我们就可以倒着DP!
f i , 0 / 1 f_{i,0/1} fi,0/1 为由B / A走到第 i i i 个点,两个人都绝顶聪明所得的结果(两个人的最优方案组成的结果),结果是指A比B多的分
那我们反着建边,然后按照拓扑序DP就好啦,注意题目要求了A先走,所以输出的是 f 1 , 1 f_{1,1} f1,1


>代码

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#define LL long long
#define inf 5000000000000000
#define N 200010
using namespace std;

queue<int> Q;
struct edge
{
    
    
	int to, nxt; LL a, b;
} e[500010];
int n, m, cnt, h[N], d[N];
LL f[N][5];

int main()
{
    
    
	int u, v; LL a, b;
	scanf ("%d%d", &n, &m);
	for (int i = 1; i <= m; i++)
	{
    
    
		scanf ("%d%d%lld%lld", &u, &v, &a, &b);
		e[++cnt] = (edge){
    
    u, h[v], a, b}; h[v] = cnt;
		d[u]++;
	}
	for (int i = 1; i <= n; i++)
	  f[i][0] = inf, f[i][1] = -inf;
	f[n][0] = f[n][1] = 0;
	Q.push (n);
	while (!Q.empty())
	{
    
    
		int u = Q.front();
		Q.pop();
		for (int i = h[u]; i; i = e[i].nxt)
		{
    
    
			int v = e[i].to;
			f[v][0] = min (f[v][0], f[u][1] - e[i].b);
			f[v][1] = max (f[v][1], f[u][0] + e[i].a);
			d[v]--;
			if (!d[v]) Q.push (v); 
		}
	}
	printf ("%lld", f[1][1]);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_43010386/article/details/121237148