首页 > 其他分享 >关于一类偏序问题

关于一类偏序问题

时间:2024-09-18 13:34:48浏览次数:6  
标签:偏序 rt int fy Alice fx 关于 rm 一类

对于一类依赖偏序关系计算答案的问题,由于我们只关注元素之间的大小关系,从而可以通过特殊的枚举方式来避免多种情况分类讨论。常见方法有:

  • \(\mathrm{<, >}\) :通过从小到大的方式依次考虑元素。

  • \(\mathrm{abs, max, min}\):通过拆成 \(<\) 或 \(>\) 的形式后,再从小到大考虑。

一些例题:

[模拟赛]dist

Statement:

给定一棵 \(n(n \le 10^6)\) 个节点带边权的树,定义 \(\mathrm{Min}(x, y)\) 是 \((x, y)\) 路径上的边权最小值。求 \(\max_{r = 1}^n {\sum_{v \ne i} \mathrm{Min}(r, v)}\)。

Solution:

我们只关注路径上最小的一条边,于是按边权从小到大依次考虑边带来的贡献,然后分成两个连通块做。但这样太慢了,所以逆向的进行合并,用并查集维护即可。

qwq
#include<bits/stdc++.h>
#pragma GCC optimize(3, "Ofast", "inline")
#define int long long
using namespace std;

const int N = 1e6 + 10;

int n, fa[N], siz[N], val[N];
struct Edge{
	int u, v, w;
}E[N];
bool cmp(struct Edge E1, struct Edge E2){
	return E1.w > E2.w;
}
int findfa(int x){return fa[x] = (fa[x] == x) ? x : findfa(fa[x]);}

void merge(int x, int y, int w){
	int fx = findfa(x), fy = findfa(y);
	if(fx == fy) return; if(siz[fx] < siz[fy]) swap(fx, fy); 
	val[fx] = max(val[fx] + siz[fy] * w, val[fy] + siz[fx] * w);
	fa[fy] = fx; siz[fx] += siz[fy];
}

signed main(){
//	freopen("dist3.in", "r", stdin);
	freopen("a.in", "r", stdin);
	freopen("a.out", "w", stdout);
	ios::sync_with_stdio(0);
	cin.tie(0); cout.tie(0);
	cin >> n; for(int i = 1; i <= n; i++) siz[i] = 1, fa[i] = i;
	for(int i = 1; i < n; i++) cin >> E[i].u >> E[i].v >> E[i].w;
	sort(E + 1, E + n, cmp);
	for(int i = 1; i < n; i++) merge(E[i].u, E[i].v, E[i].w);
	cout << val[findfa(1)];
	
	return 0;
}

[模拟赛]博弈游戏

Statement:

\(\rm Alice\) 和 \(\rm Bob\) 正在一个有向图上玩游戏。初始图上的某个节点上放着棋子,他们轮流进行操作,每次选择棋子所在节点的一条出边把棋子移过去,如果没有出边则游戏直接结束。\(\rm Alice\) 先手,游戏在 \(10^{100}\) 步后结束。节点的分数恰好是它的编号(从 \(1\) 开始编号),\(\rm Alice\) 的最终得分是棋子所经过的节点的分数的最大值。\(\rm Alice\) 想最大化她的得分,\(\rm Bob\) 想最小化 \(\rm Alice\) 的得分。请问最优策略下,从每个节点出发,\(\rm Alice\) 的得分是多少?

Solution:

令 \(f_{u, 1/0}\) 是 \(\rm Alice\)/\(\rm Bob\) 执棋时的得分。显然有:

\[\begin{aligned} f_{u, 0} &= \max(u, \max(f_{v, 1} | \exists (u, v))) \\ f_{u, 1} &= \max(u, \min(f_{v, 0} | \exists (u, v))) \end{aligned} \]

注意到 \(\max, \min\) 这类的偏序关系,于是考虑从大到小考虑加入每个点,并逐步确定每个状态的答案。假设现在枚举到点 \(u\),假设 \(f_{u, 0 / 1}\) 之前没有被确定下来,那么显然 \(f_{u, 0/1} = u\)。那么我们将新确定的答案加入到一个更行队列中,假设现在的状态是 \((u, id)\):

  • \(id = 0\):显然我们更新的是一些点的 \(f_{v, 1}\),那么注意到我们在从大到小枚举的过程中,最后一次更新到 \(f_{v, 1}\) 时才会对 \(f_{v, 1}\) 产生贡献,于是我们动态更行他的入度,当 \(v\) 的入度变为 \(0\) 时,就将 \(f_{v, 1}\) 赋值为 \(f_{u, 0}\)。

  • \(id = 1\):此时更新的是一些点的 \(f_{v, 0}\),只要 \(f_{v, 0}\) 没有被更新过,那么 \(f_{u, 1}\) 就是他的所有后继中最小的那个了。

拿队列更新就可以了。、

qwq
#include<bits/stdc++.h>
#define pir pair<int, int> 
#pragma GCC optimize(3, "Ofast", "inline")
using namespace std;

const int N = 1e5 + 10;

int n, m, out[N], f[N][2];

struct edges{
	int v, next;
}edges[N << 1];
int head[N], idx;

void add_edge(int u, int v){
	edges[++idx] = {v, head[u]};
	head[u] = idx;
}
void solve(int rt){
	queue<pir> Q;
	if(!f[rt][0]) Q.push(make_pair(rt, 0)), f[rt][0] = rt;
	if(!f[rt][1]) Q.push(make_pair(rt, 1)), f[rt][1] = rt;
	while(!Q.empty()){
		int u = Q.front().first, id = Q.front().second; Q.pop();
//		cout << u << " " << id << " " << f[u][id] << "\n";
		for(int i = head[u]; i; i = edges[i].next){
			int v = edges[i].v;
			if(id == 0 && (!f[v][1])) f[v][1] = rt, Q.push(make_pair(v, 1));
			else if(id == 1){
				out[v]--;
				if(!out[v]) f[v][0] = rt, Q.push(make_pair(v, 0));
			}
		}
	}
}

signed main(){
//    freopen("game.in", "r", stdin);
//    freopen("game.out", "w", stdout);
	ios::sync_with_stdio(0);
	cin.tie(0); cout.tie(0);
	cin >> n >> m;
	for(int i = 1; i <= m; i++){
		int x, y; cin >> x >> y;
		add_edge(y, x); out[x]++;
	}
	for(int i = n; i > 0; i--) solve(i);
	for(int i = 1; i <= n; i++) cout << f[i][1] << " ";
	
	return 0;
}

标签:偏序,rt,int,fy,Alice,fx,关于,rm,一类
From: https://www.cnblogs.com/little-corn/p/18416646

相关文章

  • 关于话语体系
    现在(2024.09.17)的我认为,作为男人,需要有自己的一套话语体系。需要话语体系的原因人心易变,沟通理解需要成本。人心易变。相比天道,人心的变化有时候看起来毫无规律。必须有自己的话语体系,对外说话有维持不变的点。话语本身具有力量。不是满足所有人,而是让部分人尽量能接受,满......
  • 关于Java使用MinIO文件服务器操作文件
    Java使用Minio上传文件示例代码1.Minio介绍MinIO是一个基于ApacheLicensev3.0开源协议的对象存储服务。它兼容亚马逊S3云存储服务接口,非常适合于存储大容量非结构化的数据,例如图片、视频、日志文件、备份数据和容器/虚拟机镜像等,而一个对象文件可以是任意大小,从几kb到最大5......
  • 【生成对抗网络GAN】最全的关于生成对抗网络Generative Adversarial Networks,GAN的介
    【生成对抗网络GAN】最全的关于生成对抗网络GenerativeAdversarialNetworks,GAN的介绍!!【生成对抗网络GAN】最全的关于生成对抗网络GenerativeAdversarialNetworks,GAN的介绍!!文章目录【生成对抗网络GAN】最全的关于生成对抗网络GenerativeAdversarialNetworks,GAN的......
  • 关于联合和枚举
    1.联合体类型的声明像结构体⼀样,联合体也是由⼀个或者多个成员构成,这些成员可以不同的类型。但是编译器只为最⼤的成员分配⾜够的内存空间。联合体的特点是所有成员共⽤同⼀块内存空间。所以联合体也叫:共⽤体。//联合类型的声明unionUn{charc;inti;}; 2.联合......
  • 教育部等十八部门关于加强新时代中小学科学教育工作的意见 20240917_085127
    原文教育部等十八部门关于加强新时代中小学科学教育工作的意见_国务院部门文件_中国政府网https://www.gov.cn/zhengce/zhengceku/202305/content_6883615.htm概述教育部等十八部门联合发布此意见,强调要加强科学教育,推动校内校外融合,规范科技类校外培训。这一政策为少儿编程教......
  • 关于IP地址、子网掩码、主机地址和网络地址的关系的详细例子
    前言:大家好很高兴我们又见面了,那么在这一篇博客中我将简单论述IP地址、子网掩码、主机地主和网络地址的关系.以及如何进行转换,方便大家理解与记忆.        :)关于IP地址、子网掩码、主机地主和网络地址的关系:####基本概念* **IP地址**:由32位(4个字节)组成,......
  • 关于Spring Boot+MySQL的房地产销售管理系统
    ​博客主页:   曾几何时…项目背景时代的进步使人们的生活实现了部分自动化,由最初的全手动办公已转向手动+自动相结合的方式。比如各种办公系统、智能电子电器的出现,都为人们生活的享受提供帮助。采用新型的自动化方式可以减少手动的办公时间,增加正确率从而增加人们......
  • C++入门基础知识71(高级)——【关于C++ 模板】
    成长路上不孤单......
  • 关于数据在内存中如何存储
    1.整数在内存中的存储在讲解操作符的时候,我们就讲过了下⾯的内容:整数的2进制表⽰⽅法有三种,即原码、反码和补码有符号的整数,三种表⽰⽅法均有符号位和数值位两部分,符号位都是⽤0表⽰“正”,⽤1表⽰“负”,最⾼位的⼀位是被当做符号位,剩余的都是数值位。 正整数的原、反、......
  • 关于码元 带宽 传输速率 奈奎斯特定理的理解
    首先是码元,码元代表的是固定时长的信号波形表示一位k进制数字,尤其注意可以是半个周期,也可以是数个周期,只需要注意是在固定时长就行,不与频率有直接关系,只要在带宽频率所显示的范围内并且可以被准确检测到数据就行。带宽,带宽应为能收到的最快频率和最慢频率的差值,单位为HZ。传输速......