• 【题解】道路相遇


    道路相遇

    ( ext{Solution:})

    题意就是对于 ((u,v)) 找有多少个必经点。

    必经边就很简单了,直接上边双缩点。这里我们用圆方树解决必经点问题。

    考虑到圆方树的性质:方点和圆点一定是相邻的,没有一个圆点连圆点,也没有一个方点连方点。

    而对于两点的必经点,就是这条路径上的割点个数,也就是方点个数。

    那方点个数不就恰好是路径长度除以 (2)(-1) 吗,然后加上题目要求的原来的两个点就完成了。

    注意这题卡常:一个是空间开大,一个是在 tarjan 的时候就进行建图,避免使用 vector ,还有注意空间别开小,这里提示空间开小导致了 MLE.

    还有,链一类的东西也是有圆方树的,每相邻两个点构成点双,并且除了度为 (1) 的节点都是割点,它们可以满足圆方相邻的树结构。

    #include<bits/stdc++.h>
    using namespace std;
    const int N=2e6+10;
    int head[N],Head[N],tot,tto,n,m;
    struct E{int nxt,to;}e[N],edge[N<<1];
    inline void link(int x,int y,int w=0){
    	if(w){
    		edge[++tto]=(E){Head[x],y};
    		Head[x]=tto;
    		return;
    	}
    	e[++tot]=(E){head[x],y};
    	head[x]=tot;
    }
    int dfn[N],low[N],dfstime,top,st[N],dep[N],Q;
    int node,siz[N],son[N],ttop[N],pa[N];
    void dfs1(int x,int fa){
    	siz[x]=1;pa[x]=fa;
    	dep[x]=dep[fa]+1;
    	for(int i=Head[x];i;i=edge[i].nxt){
    		int j=edge[i].to;
    		if(j==fa)continue;
    		dfs1(j,x);
    		siz[x]+=siz[j];
    		if(siz[j]>siz[son[x]])son[x]=j;
    	}
    }
    void dfs2(int u,int t){
    	ttop[u]=t;
    	if(!son[u])return;
    	dfs2(son[u],t);
    	for(int i=Head[u];i;i=edge[i].nxt){
    		int j=edge[i].to;
    		if(j==son[u]||j==pa[u])continue;
    		dfs2(j,j);
    	}
    }
    inline void write(int x){
    	if(x>9)write(x/10);
    	putchar(x%10+'0');
    }
    inline int Min(int x,int y){return x<y?x:y;}
    void tarjan(int x,int root){
    	st[++top]=x;
    	low[x]=dfn[x]=++dfstime;
    	if(x==root&&!head[x]){
    		++node;
    		link(x,node,1);
    		link(node,x,1);
    		return;
    	}
    	int ch=0;
    	for(int i=head[x];i;i=e[i].nxt){
    		int j=e[i].to;
    		if(!dfn[j]){
    			ch++;
    			tarjan(j,root);
    			low[x]=Min(low[x],low[j]);
    			if(low[j]>=dfn[x]){
    				int vex=-1;
    				++node;
    				do{
    					vex=st[top--];
    					link(node,vex,1);
    					link(vex,node,1);
    				}while(vex!=j);
    				link(node,x,1);
    				link(x,node,1);
    			}
    		}
    		else low[x]=Min(low[x],dfn[j]);
    	}
    }
    int LCA(int x,int y){
    	while(ttop[x]!=ttop[y]){
    		if(dep[ttop[x]]<dep[ttop[y]])swap(x,y);
    		x=pa[ttop[x]];
    	}
    	return dep[x]<dep[y]?x:y;
    }
    inline int read(){
    	int s=0;
    	char ch=getchar();
    	while(!isdigit(ch))ch=getchar();
    	while(isdigit(ch)){
    		s=s*10-'0'+ch;
    		ch=getchar();
    	}
    	return s;
    }
    int main(){
    	n=read();m=read();
    	for(int i=1;i<=m;++i){
    		int x=read(),y=read();
    		link(x,y);link(y,x);
    	}
    	node=n;
    	for(int i=1;i<=n;++i)if(!dfn[i])top=0,tarjan(i,i);
    	for(int i=1;i<=node;++i){
    		if(!dep[i]){
    			dfs1(i,0);
    			dfs2(i,i);
    		}
    	}
    	Q=read();
    	while(Q--){
    		int u=read(),v=read();
    		int L=LCA(u,v);
    		write((dep[u]+dep[v]-dep[L]-dep[L])/2+1);
    		putchar('
    ');
    	}
    	return 0;
    }
    
  • 相关阅读:
    进度条
    html5 表单新增事件
    html5 表单的新增type属性
    html5 表单的新增元素
    html5 语义化标签
    jq 手风琴案例
    codeforces 702D D. Road to Post Office(数学)
    codeforces 702C C. Cellular Network(水题)
    codeforces 702B B. Powers of Two(水题)
    codeforces 702A A. Maximum Increase(水题)
  • 原文地址:https://www.cnblogs.com/h-lka/p/15312212.html
Copyright © 2020-2023  润新知