洛谷 P7520

摘要:
Logo问题表面的传输门真正控制树的问题不是sb。由于这个问题的数据范围允许(n^2)算法通过,我们可以考虑建立一个支配树。具体来说,我们枚举每个点,并从图中临时删除该点。如果删除后无法到达图中的另一个点,则它将位于的支配集中。通过这种方式,我们可以为整个DAGDFS再次计算每个点的DFS阶数,然后将DFS阶数最大的点作为支配树中每个点的父级。

洛谷题面传送门

真·支配树不 sb 的题。

首先题面已经疯狂暗示咱们建出支配树对吧,那咱就老老实实建呗。由于这题数据范围允许 (n^2)​ 算法通过,因此可以考虑 (mathcal O(n^2))​ 地建立支配树,具体来说我们枚举每个点 (x)​,将这个点暂时地从图中删除,如果对于图中另一个点 (y)​ 满足删除 (x)(1) 不能到达 (y),那么 (x) 就在 (y) 的支配集中,这样我们再对整个 DAG DFS 一遍求出每个点的 DFS 序,然后取 DFS 序最大的点作为每个点在支配树上的父亲即可。

接下来考虑怎样计算答案。首先显然的一件事情是,我们加入一条边后最多只会让某些点的支配集大小变小,而不会使支配集大小变大,因此我们只需考虑有哪些点在加入这条边后,存在某个点原来能支配它而现在不能即可。注意到一个性质,就是对于一个点 (x)​,如果 (fa_x)​(当然有些人喜欢称这个东西为 (idom_x)​,反正能看懂就行了吧)的支配集改变,那么 (x)​ 的支配集也会改变。因为根据支配树的性质,每个点的支配集一定是该点到 (1)​ 路径上所有点组成的集合,因此如果 (fa_x)​ 的支配集改变,就必然存在某个 (fa_x)​ 的祖先 (y)​,满足存在路径 (1 o fa_x)​ 且不经过 (y)​,这样就存在路径 (1 o fa_x o x)​ 不经过 (x)​,(y)​ 就从 (x)​ 的支配集中消失了。同理,如果 (fa_x)​ 的支配集没变,但 (x)​ 的支配集改变,必然是因为 (fa_x)​ 无法支配 (x)​,因为如果存在某个 (x)​ 的祖先 (y e fa_x)​,满足 (y) 不再支配 (x)(y) 能支配 (fa_x),那就能推出这个 (1 o x) 且不经过 (y) 的路径肯定不经过 (fa_x),从而 (fa_x) 不支配 (x)

因此我们考虑每次询问对整棵树进行 DFS,如果走到一个点发现 (fa_x) 不支配 (x),答案就加上 (x) 子树的大小并 return,那么怎么判断 (fa_x) 是否支配 (x) 呢?显然如果 (fa_x) 不支配 (x) 那么必然存在路径 (1 o u o v o x) 满足这条路径不经过 (fa_x),而这又 obviously 等价于 (1 o u,v o x) 均不经过 (fa_x),前者可以通过建支配树时预处理出的“删掉点 (x) 后是否存在 (1 o y) 的路径的数组 (ban_{x,y})”求出,而关于后者我们发现都是形如”删掉 (fa_x)(x) 能否在反图上到达 (y)“,因此我们再建一个 (ban\_fa_{x,y}) 维护这个东西即可。时间复杂度 (mathcal O(n^2+nq))

卡常技巧:交换 (ban)(ban\_fa) 的两维后,效率大约能快 25%,具体原理见这儿

const int MAXN=3e3;
const int MAXM=MAXN<<1;
int n,m,qu;
struct graph{
	int hd[MAXN+5],nxt[MAXM+5],to[MAXM+5],ec=0;
	void adde(int u,int v){to[++ec]=v;nxt[ec]=hd[u];hd[u]=ec;}
} g,rv_g,dt;
int dfn[MAXN+5],rid[MAXN+5],tim=0,fa[MAXN+5];
bool ban[MAXN+5][MAXN+5],ban_fa[MAXN+5][MAXN+5];
void dfs(int x){
	rid[dfn[x]=++tim]=x;
	for(int e=g.hd[x];e;e=g.nxt[e]){
		int y=g.to[e];if(!dfn[y]) dfs(y);
	}
}
void dfs_ban(int x,int ban_id){
	if(x==ban_id) return;ban[x][ban_id]=1;
//	printf("{%d,%d}
",ban_id,x);
	for(int e=g.hd[x];e;e=g.nxt[e]){
		int y=g.to[e];
		if(!ban[y][ban_id]) dfs_ban(y,ban_id);
	}
}
void dfs_ban_fa(int x,int ban_id){
	if(x==fa[ban_id]) return;ban_fa[x][ban_id]=1;
	for(int e=rv_g.hd[x];e;e=rv_g.nxt[e]){
		int y=rv_g.to[e];
		if(!ban_fa[y][ban_id]) dfs_ban_fa(y,ban_id);
	}
}
int siz[MAXN+5];
void dfssiz(int x){
	siz[x]=1;
	for(int e=dt.hd[x];e;e=dt.nxt[e]){
		int y=dt.to[e];dfssiz(y);
		siz[x]+=siz[y];
	}
}
int X,Y,res=0;
void dfscalc(int x){
	if(x^1){
		if(ban[X][fa[x]]&&ban_fa[Y][x]){
			res+=siz[x];return;
		}
	} for(int e=dt.hd[x];e;e=dt.nxt[e]){
		int y=dt.to[e];dfscalc(y);
	}
}
int main(){
	scanf("%d%d%d",&n,&m,&qu);
	for(int i=1,u,v;i<=m;i++){
		scanf("%d%d",&u,&v);
		g.adde(u,v);rv_g.adde(v,u);
	} dfs(1);for(int i=1;i<=n;i++) dfs_ban(1,i);
//	for(int i=1;i<=n;i++) printf("%d %d
",dfn[i],rid[i]);
	for(int i=1;i<=n;i++) for(int j=1;j<=n;j++)
		if(!ban[j][i]&&(i^j)) chkmax(fa[j],dfn[i]);
	for(int i=2;i<=n;i++) fa[i]=rid[fa[i]];fa[1]=0;
	for(int i=2;i<=n;i++) dt.adde(fa[i],i),dfs_ban_fa(i,i);
//	for(int i=2;i<=n;i++) printf("%d
",fa[i]);
	dfssiz(1);
	while(qu--){scanf("%d%d",&X,&Y);res=0;dfscalc(1);printf("%d
",res);}
	return 0;
}

免责声明:文章转载自《洛谷 P7520》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇MySQL----ERROR 1071 (42000): Specified key was too long; max key length is 767 bytesxml中xsd、xsi、xmlns的含义下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

随便看看

win10家庭版VMware,禁用Device/Credential Guard不兼容问题

环境vmware15pro,Windows 10家庭版。...

【使用 DOM】为DOM元素设置样式

DOCTYPE html˃设置DOM元素的样式p{border:中双绿色;背景颜色:浅灰色;}#block1{color:白色;}table{border:thinsolided;border collapse:collapse;margin:5px;float:left;}td{padding:2px;}#block2{color:yellow;font-...

unity, 设置帧率上限

使用unity制作演示,并移除所有昂贵的特效。在真正的机器上运行仍然会导致问题。最大显示帧速率为30。默认情况下,IOS设备上统一的原始帧速率限制为30。应用targetFrameRate=60;更改为最大值60。请注意,此设置对编辑器没有影响。...

【转】MUD教程--巫师入门教程4

在MUD中,为了解决定时触发某种现象,一般有两种方法,一种是通过call_out()延时呼叫,另一种就是通过心跳。于是,对于要跨起离线前后的象做牢这类的事,大多都是采用condition。附:由于大多数MUD里的心跳是每两秒调一次,5+random是5至14次,因此可以看出每一个condition被调用的时间是平均19秒。然后它会按照condition的名字...

Foxyproxy 火狐代理插件

Firefox上的插件Autoproxy一直很难使用。它永远不能更新规则,但foxyproxy可以替代它。用鼠标中键单击foxyproxy图标以在不同的代理方法之间切换。foxyproxy图标从foxhead变为蓝色,因为内容传输发生在网页中,该传输通过默认代理服务器,默认代理的初始颜色为蓝色。...

uni-app为组件uni-icons增加自定义图标(超简单)

1、找到需要的图标,这里我是在阿里巴巴图标库(https://www.iconfont.cn/)中找到对应的图标下载为svg格式备用:2、通过在线ttf编辑器打开uni.ttf文件(http://fontstore.baidu.com/static/editor/index.html#),打开之后可以看到所有的uni所有图标都在里面3、导入第一步下载好的图标...