首页 > 其他分享 >快速求图上最小点定联通块权值的Trick

快速求图上最小点定联通块权值的Trick

时间:2024-10-30 21:58:03浏览次数:1  
标签:nxt int dst Trick lst dfn 权值 求图 now

更新日志

概念

图上最小点定连通块,就是给出无向连通图上一些点,要求找出边权和最小的连通分量使这些点强连通。

现在要求这个连通块内的边权之和。

思路

先给出结论:把节点按照dfs序排序,统计所有相邻的节点以及起始点与末尾点之间的距离,将它们求和,所求的答案即为这个和除以2。

感性证明一下,可以想象一个人(或者蚂蚁,或者飞船,或者任何能沿着路走的生物,或者不是生物也行),在dfs生成树上走上、走下,依次走向每一个节点,最后走会原点,不难想象到每一条边都被他走了两遍。

稍微理性一点的话,因为是按照dfs序依次排列的,就有几种情况:

  • 一点是另一点的祖先节点,直接走下去。
  • 二者属于不同子树,先走回到公共祖先节点(必然是之前已经经过的节点),再走进一条新的路径
    重复二个操作,那么都是先走到最深的节点,再回溯到某个点,再沿着另一个路径搜索……最后回到起始点,每条边就都被走了两次。

例题

CF372D

代码

前注:非题解,不做详细讲解

#include<bits/stdc++.h>
using namespace std;

const int N=1e5+5,T=32;

int n,k;
int ans;
int distal;

vector<int> vs[N];
set<int> dst;

int dp[N];
int f[N][T+5];
void brinit(){
	for(int t=1;t<=T;t++){
		for(int i=1;i<=n;i++){
			f[i][t]=f[f[i][t-1]][t-1];
		}
	}
}
int lca(int a,int b){
	if(dp[a]>dp[b])swap(a,b);
	for(int t=T;t>=0;t--){
		if(dp[f[b][t]]>=dp[a])b=f[b][t];
	}
	if(a==b)return a;
	for(int t=T;t>=0;t--){
		if(f[a][t]!=f[b][t]){
			a=f[a][t];
			b=f[b][t];
		}
	}
	return f[a][0];
}
int dis(int a,int b){
	int c=lca(a,b);
	return dp[a]-dp[c]+dp[b]-dp[c];
}

int cnt;
int dfn[N];
void dfs(int now,int fa){
	dfn[now]=++cnt;
	f[dfn[now]][0]=dfn[fa];
	dp[dfn[now]]=dp[dfn[fa]]+1;
	for(auto nxt:vs[now]){
		if(nxt==fa)continue;
		dfs(nxt,now);
	}
}

void pushin(int x){
	dst.insert(dfn[x]);
	int now,lst,nxt;
	now=lst=nxt=0;
	auto plc=dst.lower_bound(dfn[x]);
	now=*plc;
	auto lstp=plc;
	if(lstp==dst.begin())lst=*dst.rbegin();
	else{advance(lstp,-1);lst=*lstp;}
	auto nxtp=plc;advance(nxtp,1);
	if(nxtp==dst.end())nxt=*dst.begin();
	else nxt=*nxtp;
	distal-=dis(lst,nxt);
	distal+=dis(lst,now);
	distal+=dis(now,nxt);
}

void throut(int x){
	int now,lst,nxt;
	now=lst=nxt=0;
	auto plc=dst.lower_bound(dfn[x]);
	now=*plc;
	auto lstp=plc;
	if(lstp==dst.begin())lst=*dst.rbegin();
	else{advance(lstp,-1);lst=*lstp;}
	auto nxtp=plc;advance(nxtp,1);
	if(nxtp==dst.end())nxt=*dst.begin();
	else nxt=*nxtp;
	distal+=dis(lst,nxt);
	distal-=dis(lst,now);
	distal-=dis(now,nxt);
	dst.erase(dfn[x]);
}

inline bool check(){
	return distal/2+1<=k;
}

int main(){
	ios::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);
	cin>>n>>k;
	int a,b;
	for(int i=1;i<n;i++){
		cin>>a>>b;
		vs[a].push_back(b);
		vs[b].push_back(a);
	}
	dfs(1,1);
	brinit();
	for(int i=0,j=1;i<=n;pushin(++i)){
		while(!check()){
			throut(j++);
		}
		ans=max(ans,i-j+1);
	}
	cout<<ans;
	return 0;
}

标签:nxt,int,dst,Trick,lst,dfn,权值,求图,now
From: https://www.cnblogs.com/HarlemBlog/p/18514666

相关文章

  • C++刷题tricks整理
    是自己做题中整理的常用C++操作,此为存档。STL容器容器适配器,STL里面的vector/array/deque/set/map/unordered_set可以直接使用==比较是否相等:vector<int>a;deque<int>a;map<int,string>a;unordered_map<int,string>a;set<int>a;unordered_set<int>a;forward_lis......
  • CTF 的基础知识 & 题型 & Trick总结
    references:12webphp语法基础references:1php脚本的基本格式:<?php//codinghere?>php代码同样以;结尾。php文件的后缀名大多是php,也有诸如php5php4phps之类,如果普通的后缀名被拦截不妨试试其他的。php变量用$来定义,大小写敏感,但是不用声明数据类型......
  • tricks
    二分答案P2824排序有时候可以尝试二分最后的答案,把不好维护的东西变成\(0\)和\(1\)。操作分块P5443桥梁将操作分块维护,一般适用于可以很好维护静态询问但是需要支持修改的情况(?)。状态压缩去除后效性P2157学校食堂dp有后效性但影响范围很小可以考虑把后续决策压缩起......
  • [Trick] 格路记数 - 反射容斥
    Perface模拟赛不会被冲烂了。ProblemI从\((0,0)\)到\((n,m)\)方案数。解法:\(C(n+m,m)\)。ProblemII从\((0,0)\)到\((n,m)\)方案,但是不能经过\(y=x+b\)的直线。解法:考虑映射法。以一条路径第一次碰到直线的位置为起点,之后所有的路线和\(y=x+b\)对称,这样可......
  • Tricks(长期更新)
    会很杂,尽量分类,每个trick会配题。难以分类的难以分类可能只是自己太菜了。曼哈顿距离与切比雪夫距离的转化对于两点\((x_1,y_1),(x_2,y_2)\),曼哈顿距离为\(|x_1-x_2|+|y_1+y_2|\),切比雪夫距离为\(\max(|x_1-x_2|,|y_1-y_2|)\)。画图可以发现到原点的曼哈顿距离为\(1\)的点形......
  • 位运算 之 小 trick
    异或 只出现一次的数字(其他两次) 136.只出现一次的数字一串数中,每个数都出现2次,只有一个数出现1次,求出这个数。考察异或的性质,根据a^a=0,a^0=a那么就对每个数异或一下即可。然后根据交换律,每个数都异或了之后,相同的都归0了,剩下一个就自动求出来了。大概是这样(找不到C+......
  • 关于离散化+Trick
    离散化干嘛用的不多说。你不会去问度娘吗板板经常忘又懒得找。遂写一模板暂存。//a为原数组,b为a的副本voidversion1(){ sort(b+1,b+1+n); intsiz=unique(b+1,b+1+n)-b-1; for(inti=1,k;i<=n;i++) a[i]=lower_bound(b+1,b+1+siz,a[i])-b-1;}unordered_map<int,i......
  • (可持久化)权值线段树
    权值线段树就是把类型存在线段树上,每个下标存的是类型的数量。可以用来做离线的平衡树,如果值域范围小的话可以在线,只有一只\(\log\)。平衡树六种操作:插入\(x\)就是把\(x\)上的值加\(1\)。modify(1,1,n,x,1);删除一个\(x\)就是把\(x\)上的值加\(-1\)。modify(1,......
  • 一些常用tricks,基础知识收录
    uoj转,YAML的ppt格式不想改了,将就看看吧|一些常用tricks,基础知识收录byzsjchildren:|题目链接:T1:CF504EMishaandLCPonTreeT2:LuoguP2617DynamicRankingsT3:LuoguP4197PeaksT4:LuoguP4690[Ynoi2016]镜中的昆虫T5:H1079.E.‘MinamiKotori......
  • noip2014联合权值
    noip2014联合权值题目描述无向连通图G有n个点,n-1条边。点从1到n依次编号,编号为i的点的权值为Wi,每条边的长度均为1。图上两点(u,v)的距离定义为u点到v点的最短距离。对于图G上的点对(u,v),若它们的距离为2,则它们之间会产生Wu×Wv的联合权值。请问图G上所有可产生......