• LuoGu P2783 有机化学之神偶尔会做作弊


    题目传送门
    人生第一道黑题呢,虽然这题是黑题中的水题并且我调了一整节课,但是我还是很兴奋啊.毕竟人生第一道黑题啊
    这个题根据题意,先把整个图进行tarjan缩点,建出一棵树,对于每一组询问,两点之间的距离+1就是答案,求出他们的LCA,两点到LCA的距离之和就是两点之间的距离
    然后....LCA我采用的是树剖方法,然后对于这个无向图中的强连通分量(其实是叫双连通分量),和有向图中强连通分量的求法并没有什么太大的差别
    dfs时,注意不要让它走向父节点就好了
    然后,,,,这题剩下的就是调试了

    #include <iostream>
    #include <cstdlib>
    #include <cstdio>
    #define min(a,b) (a<b?a:b)
    
    using namespace std;
    
    const int M=5e4+5;
    const int N=1e4+5;
    
    struct edge{
    	int to,next,pre;
    }e[(M<<1)],t[(M<<1)];
    
    int n,m,q,dfn[N],low[N],_top;
    int siz[N],f[N],son[N],deep[N];
    int head[N],tot,top[N],s[N],cnt;
    int Tot,Head[N],total,idx[N],anc;
    bool ins[N];
    
    inline int read(){
    	int x=0,f=1;char ch=getchar();
    	while(ch<'0'||ch>'9'){
    		if(ch=='-') f=-1;
    		ch=getchar();
    	}
    	while(ch>='0'&&ch<='9'){
    		x=x*10+ch-'0';
    		ch=getchar();
    	}
    	return x*f;
    }
    
    inline void build_edge(int u,int v){
    	e[++tot].next=head[u];head[u]=tot;
    	e[tot].to=v;e[tot].pre=v;return ;
    }
    
    inline void build_tree(int u,int v){
    	t[++Tot].next=Head[u];Head[u]=Tot;
    	t[Tot].to=v;t[Tot].pre=v;return ;
    }
    
    inline void tarjan(int cur,int anc){
    	s[++_top]=cur;dfn[cur]=low[cur]=++cnt;ins[cur]=true;
    	for(register int i=head[cur];i;i=e[i].next){
    		register int k=e[i].to;
    		if(k==anc) continue;
    		if(!dfn[k]){
    			tarjan(k,cur);
    			low[cur]=min(low[cur],low[k]);
    		}else if(ins[k]) low[cur]=min(low[cur],dfn[k]);
    	}
    	if(low[cur]==dfn[cur]){
    		++total;
    		while(s[_top+1]!=cur){
    			idx[s[_top]]=total;
    			ins[s[_top--]]=false;
    		}
    	}
    	return ;
    }
    
    inline void dfs1(int now,int anc,int dep){
    	deep[now]=dep;f[now]=anc;siz[now]=1;int maxson=-1;
    	for(register int i=Head[now];i;i=t[i].next){
    		register int k=t[i].to;if(k==anc) continue;
    		dfs1(k,now,dep+1);siz[now]+=siz[k];
    		if(siz[k]>maxson) maxson=siz[k],son[now]=k;
    	}
    	return ;
    }
    
    inline void dfs2(int now,int topf){
    	top[now]=topf;if(!son[now]) return ;dfs2(son[now],topf);
    	for(int i=Head[now];i;i=t[i].next){
    		int k=t[i].to;
    		if(k==f[now]||k==son[now]) continue;
    		dfs2(k,k);
    	}
    	return ;
    }
    
    inline int LCA(int x,int y){
    	while(top[x]!=top[y]){
    		if(deep[top[x]]<deep[top[y]]) y=f[top[y]];
    		else x=f[top[x]];
    	}
    	return (deep[x]<deep[y]?x:y);
    }
    
    inline void print(int x){
    	if(!x) return ;
    	print(x>>1);
    	printf("%d",x&1);
    }
    
    int main(){
    	n=read();m=read();
    	for(register int i=1;i<=m;++i){
    		register int u,v;
    		u=read();v=read();
    		build_edge(u,v);build_edge(v,u);
    	}
    	for(register int i=1;i<=n;++i) if(!dfn[i]) tarjan(i,0);
    	for(register int i=1;i<=n;++i)
    		for(register int j=head[i];j;j=e[j].next){
    			register int k=e[j].to;
    			if(idx[i]!=idx[k])
    				build_tree(idx[i],idx[k]);//build_tree(idx[k],idx[i]);
    		}
    	dfs1(1,0,1);dfs2(1,1);
    	q=read();
    	while(q--){
    		register int u=read(),v=read();
    		u=idx[u];v=idx[v];anc=LCA(u,v);
    		register int ans;
    		ans=deep[u]+deep[v]-(deep[anc]<<1)+1;
    		print(ans);printf("
    ");
    	}
    	return 0;
    }
    
    May you return with a young heart after years of fighting.
  • 相关阅读:
    使用SWFUpload进行多文件上传
    TSQL递归
    Silverlight之视频录制
    Silverlight之摄像头麦克风使用
    Silverlight之文件上传组件
    SQL FOR XML
    XAML开发入门之XAML核心语法
    Ajax技术三种实现方式之xmlhttp+httphandler篇 (三)
    Ext中超时设定 ext.ajax.timeout
    后台执行js先执行前端的JS函数,再执行后台函数的按钮实
  • 原文地址:https://www.cnblogs.com/Equinox-Flower/p/9630462.html
Copyright © 2020-2023  润新知