首页 > 其他分享 >题解 CF825E【Minimal Labels】

题解 CF825E【Minimal Labels】

时间:2023-04-22 22:24:24浏览次数:31  
标签:int 题解 出度 Labels CF825E 权值 分配权 define

偶然间翻到三个月前写的这个题,发现现有的题解均未给出解法的正确性证明,只是不明不白地写了一些对理解做法毫无帮助的话。我认为解法的正确性并不显然,因此这篇题解主要给出正确性证明,补上逻辑漏洞。

解法与其他题解一样,即:建反图,然后跑拓扑排序,每次优先取出可以取出的编号最大的点,从 \(n\) 到 \(1\) 赋权值。

这似乎有点反直觉:为什么倒着做就恰好能满足字典序最小呢?相信大多数人的第一反应都是正着做,这也是我认为正确性并不显然的原因。

证明:

以下“入边”“出边”“入度”“出度”等均为原图上的。

考虑整个算法的第一步,也就是分配权值 \(n\)。显然,权值 \(n\) 的点出度必须为 \(0\)。

我们记在上述算法中,被分配了权值 \(n\) 的点的编号为 \(u\)。利用反证法,假设在另一种分配方案中,\(u\) 被分配了权值 \(x\)(\(x < n\)),而 \(v\) 被分配了权值 \(n\)。由于算法中取出的 \(u\) 是编号最大的出度为 \(0\) 的点,而 \(v\) 的出度也必须为 \(0\),因此我们有 \(u > v\)。

对于这种分配方案中被分配权值 \(x+1\sim n\) 的点,我们可以将它们重新分配 \(x\sim n-1\) 的权值,并将 \(u\) 重新分配 \(n\) 的权值,仍然得到合法的分配方案。这是因为:点 \(u\) 出度为 \(0\),将 \(u\) 的权值增大并不会影响 \(u\) 与其余节点的合法性;并且考虑去掉点 \(u\) 的其他节点,重新分配权值相当于对原来的权值进行离散化,不改变偏序关系。

因此,我们可以重新分配权值使得 \(u\) 的权值为 \(n\)。并且,由于 \(u > v\),重新分配权值后答案的字典序减小。

由于点 \(u\) 的出度为 \(0\),给它分配了最大的权值 \(n\) 之后,其余节点与 \(u\) 之间必然合法,只需要求出其余节点的最小字典序答案即可。因此将点 \(u\) 以及它的所有入边都删除,得到规模为 \(n-1\) 的子问题。又显然当 \(n=1\) 时,算法可以给出最小字典序答案,因此算法正确性得证。\(\square\)

//By: OIer rui_er
#include <bits/stdc++.h>
#define rep(x,y,z) for(int x=(y);x<=(z);x++)
#define per(x,y,z) for(int x=(y);x>=(z);x--)
#define debug(format...) fprintf(stderr, format)
#define fileIO(s) do{freopen(s".in","r",stdin);freopen(s".out","w",stdout);}while(false)
#define likely(exp) __builtin_expect(!!(exp), 1)
#define unlikely(exp) __builtin_expect(!!(exp), 0)
using namespace std;
typedef long long ll;
const int N = 1e5+5; 

int n, m, deg[N], id[N], tms;
vector<int> e[N];
template<typename T> void chkmin(T& x, T y) {if(x > y) x = y;}
template<typename T> void chkmax(T& x, T y) {if(x < y) x = y;}
void toposort() {
	priority_queue<int> q;
	rep(i, 1, n) if(!deg[i]) q.push(i);
	while(!q.empty()) {
		int u = q.top(); q.pop();
		id[u] = ++tms;
		for(int v : e[u]) if(!--deg[v]) q.push(v);
	}
}

int main() {
	scanf("%d%d", &n, &m);
	rep(i, 1, m) {
		int u, v;
		scanf("%d%d", &u, &v);
		e[v].push_back(u);
		++deg[u];
	}
	toposort();
	rep(i, 1, n) printf("%d%c", n+1-id[i], " \n"[i==n]);
	return 0;
}

标签:int,题解,出度,Labels,CF825E,权值,分配权,define
From: https://www.cnblogs.com/ruierqwq/p/CF-825E.html

相关文章

  • 第九周题解QAQ
    A-Howmanyprimenumbers1#include<iostream>2usingnamespacestd;3boolisprime(intx)//判断素数(朴素版方法)4{5if(x<2)returnfalse;6for(inti=2;i<=x/i;i++)7if(x%i==0)returnfalse;8returntrue;9}10int......
  • CF1714D 题解
    CF1714D题解description给定黑色文本\(t\)和\(n\)个字符串\(s_1,s_2...s_n\).一次操作可以将\(t\)中与\(s_i\)相等的子串涂成红色。一个位置多次涂色后仍是红色。\(s_i\)可以使用多次。求将\(t\)涂成红色的最小次数,并输出方案。无解输出-1.\(|t|\leq100\)......
  • 题解:【CF235D】Graph Game
    题目链接根据期望的线性性,一次操作使得接下来要递归处理\(|G|\)个点,将这些贡献分摊到\(|G|\)个点上,这样我们接下来只需要计算概率。首先考虑如果是树怎么做。操作等价于随机一个排列,顺次删掉排列中的点,并求出删掉当前点之前其所处的连通块的大小。记当前\(x\)为点分治中心......
  • 二叉树经典题解
    目录......
  • winform设置背景图闪屏问题解决
    直接将以下代码复制粘贴到出现闪屏的窗体中即可:#region解决添加背景图片时闪屏的问题protectedoverrideCreateParamsCreateParams{get{CreateParamscp=base.CreateParams;cp.Ex......
  • 暗的连锁 题解
    题目描述Dark是一个无向图,图中有\(n\)个结点和两类边,一类边被称为主要边,而另一类被称为附加边。Dark有\(n-1\)条主要边,并且Dark的任意两个结点之间都存在一条只由主要边构成的路径。另外,Dark还有\(m\)条附加边。你的任务是把Dark斩为不连通的两部分。一开始Dark......
  • ABC298E 题解
    前言题目传送门!更好的阅读体验?题解区的代码都好丑啊,嘲讽。思路对于这种概率题,正常人都能反应到这是dp。所以:\(dp_{t,i,j}\)表示:当前是第\(t\)回合,Tak在\(i\)位置,Aok在\(j\)位置,概率。如果这样设状态的话,转移方程就会非常一眼(刷表):\[dp_{t,\min(i+\texttt{st......
  • [P8766 [蓝桥杯 2021 国 AB] 异或三角]题解
    P8766[蓝桥杯2021国AB]异或三角题目描述分析题目中给出了三个限制首先我们不妨设\(a,b\ltc\),则而由于我们把\(c\)作为了最大值,原题需要有序对\((a,b,c)\)所以\(ans\ast3\)1.\(1\leqa,b,c\leqn\)2.\(a\oplusb\oplusc=0\)3.\(a+b\gtc\)而在枚举过程中,......
  • P1350 车的放置 题解
    一、题目描述:给你一个网格棋盘,a,b,c,d 表示了对应边长度,也就是对应格子数。例如,当a=b=c=d=2时,对应如下面这样一个棋盘:想要在这个棋盘上放 k棋子,也就是这 k 个棋子没有两个在同一行,也没有两个在同一列,问有多少种方案。数据保证 0......
  • [ARC138D] Differ by K bits 题解
    小清新构造题。首先\(K=1\)的情况是trival的,直接格雷码即可。对于\(K>1\),我们发现题目的约束相当于\(\operatorname{popcount}(P_i\oplusP_{(i+1)\bmod2^N})=K\),考虑\(P_i\)的差分序列\(D_i\),那么\(D_i\)一定是一个恰好有\(K\)位\(1\)的二进制数,记\(S=\{i\mid......