IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> P7516 [省选联考 2021 A/B 卷] 图函数 -> 正文阅读

[C++知识库]P7516 [省选联考 2021 A/B 卷] 图函数

解析

纯纯的人类智慧题。

关键性质: v v v 可以在计算 f ( u , G ) f(u,G) f(u,G) 时产生贡献,当且仅当 G G G u , v u,v u,v 之间可以通过 [ v , n ] [v,n] [v,n] 的点互相到达。
充分性较为显然,编号更大的点不会比 v v v 先删去,所以必然在 v v v 时刻依然存在。
必要性证明:假设 v v v 时刻 u → v u\to v uv 的路径上存在一个 x ∈ [ 1 , v ) x\in [1,v) x[1,v),在 x x x 时刻图的联通性不弱于 v v v 时刻,因而必然也有 u → x u\to x ux 可达,且由于 x → v , v → u x\to v,v\to u xv,vu 皆可达,也就有 x → u x\to u xu 可达, x x x 应当被删去,矛盾。

接下来的任务就是如何维护这个东西。

floyd

对于点编号属于 [ v , n ] [v,n] [v,n] 这样的限制,不难想到 floyd。但是直接跑无法通过 n = 1000 n=1000 n=1000
然后拿大样例试了试,发现写成:

for(int k=n;k>=1;k--){
		for(int i=1;i<=k;i++){
			for(int j=i;j<=n;j++){
			  k -> update(i,j)
			}
		}
	}

答案依然是对的,并且能跑过1000了。
然后就完事了。

我们当然要想一想为什么这样是对的。
这么转移必然出问题的就是两边的点编号均大于 k k k 的情况。
如图中的 p , q p,q p,q
(高度表示点编号的相对大小)
请添加图片描述

那么我们现在就要证明:

( x , y ) (x,y) (x,y) 路径上没有经过 [ 1 , min ? ( x , y ) ) [1,\min(x,y)) [1,min(x,y)) 的点,就必然可以正确转移。

假设枚举到中转点 k k k 之前的路径都符合这个性质。
对于当前枚举的中转点 k k k,注意到我们需要求出的合法路径必然至少有一个端点是小于 k k k 的。
那么就必然能在 k k k 的某一侧找到第一个编号小于 k k k 的点 x x x k → x k\to x kx 这段路径使用 ( k , n ] (k,n] (k,n] 的点中转,不会出现现在 p , q p,q p,q 这样的窘境,所以 f ( k , x ) f(k,x) f(k,x) 当前是对的。
那么 x x x 就可以通过 k k k 连接起另一侧的 p p p ,得到正确的 f ( p , x ) f(p,x) f(p,x)
如果 ( u , p ) (u,p) (u,p) 之间有 k ′ k' k 这样的点导致 f ( u , p ) f(u,p) f(u,p) 不对怎么办?把 ( u , p ) (u,p) (u,p) 最小的点 k ′ k' k 当成 p p p 的角色来考虑,刚才的证明就还是对的。

bfs

本题看题解,还有通过 bfs 求对每个 v v v 考虑在每张图中能对多少 u u u 产生贡献的方法来做的,每次 bfs 用到一条边就直接删去,从而保证复杂度为 O ( n m ) O(nm) O(nm),也挺妙的。

代码

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define ull unsigned long long
#define debug(...) fprintf(stderr,__VA_ARGS__)
#define ok debug("OK\n")
using namespace std;

const int N=1050;
const int M=2e5+100;
const int inf=1e9;
const int mod=19921228;

inline ll read(){
	ll x(0),f(1);char c=getchar();
	while(!isdigit(c)) {if(c=='-')f=-1;c=getchar();}
	while(isdigit(c)) {x=(x<<1)+(x<<3)+c-'0';c=getchar();}
	return x*f;
}

int n,m;
int f[N][N];
ll sum[M];

signed main() {
#ifndef ONLINE_JUDGE
	freopen("a.in","r",stdin);
	freopen("a.out","w",stdout);
#endif
	//memset(f,0x3f,sizeof(f));
	n=read();m=read();
	for(int i=1;i<=m;i++){
		int x=read(),y=read();
		f[x][y]=i;
	}
	for(int i=1;i<=n;i++) f[i][i]=m+1;
	for(int k=n;k>=1;k--){
		for(int i=k;i<=n;i++) sum[min(f[i][k],f[k][i])]++;
		for(int i=1;i<=k;i++){
			//if(!f[i][k]&&!f[k][i]) continue;
			for(int j=i;j<=n;j++){
				f[i][j]=max(f[i][j],min(f[i][k],f[k][j]));
				f[j][i]=max(f[j][i],min(f[j][k],f[k][i]));
			}
		}
	}
	for(int i=m;i>=1;i--) sum[i]+=sum[i+1];
	for(int i=1;i<=m+1;i++) printf("%lld ",sum[i]);
	return 0;
}
/*
*/

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-03-17 21:52:22  更:2022-03-17 21:54:48 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 3:09:23-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码