zoukankan      html  css  js  c++  java
  • [luogu2783] 有机化学之神偶尔会做作弊

    题目链接

    洛谷.

    Solution

    边双缩点然后(lca)(dis)就好了。

    注意这里是边双,不知道为啥所有题解都说的是点双。

    边双是定义在点上的,即每个点只属于一个边双;点双是定义在边上的,即每条边只属于一个点双。

    #include<bits/stdc++.h>
    using namespace std;
     
    void read(int &x) {
        x=0;int f=1;char ch=getchar();
        for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-f;
        for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';x*=f;
    }
     
    void print(int x) {
        if(x<0) putchar('-'),x=-x;
        if(!x) return ;print(x/2),putchar(x%2+48);
    }
    void write(int x) {if(!x) putchar('0');else print(x);putchar('
    ');}
    
    #define lf double
    #define ll long long 
    
    const int maxn = 2e4+10;
    const int maxm = 1e5+10;
    const int inf = 1e9;
    const lf eps = 1e-8;
    
    int n,m;
    
    struct Tree {
    	int head[maxn],tot,fa[maxn][15],dep[maxn],vis[maxn];
    	struct edge{int to,nxt;}e[maxm<<1];
    
    	void add(int u,int v) {e[++tot]=(edge){v,head[u]},head[u]=tot;}
    	void ins(int u,int v) {add(u,v),add(v,u);}
    
    	void dfs(int x,int Fa) {
    		dep[x]=dep[Fa]+1,fa[x][0]=Fa;
    		for(int i=1;i<=14;i++) fa[x][i]=fa[fa[x][i-1]][i-1];
    		for(int i=head[x];i;i=e[i].nxt)
    			if(e[i].to!=Fa) dfs(e[i].to,x);
    	}
    
    	int lca(int x,int y) {
    		if(dep[x]<dep[y]) swap(x,y);
    		for(int i=14;~i;i--) if(dep[fa[x][i]]>=dep[y]) x=fa[x][i];
    		if(x==y) return x;
    		for(int i=14;~i;i--) if(fa[x][i]!=fa[y][i]) x=fa[x][i],y=fa[y][i];
    		return fa[x][0];
    	}
    
    	int dis(int x,int y) {return dep[x]+dep[y]-2*dep[lca(x,y)]+1;}
    }T;
    
    struct Graph {
    	int head[maxn],tot,dfn[maxn],low[maxn],dfn_cnt,bel[maxn],col,sta[maxn],top;
    	struct edge{int to,nxt;}e[maxm<<1];
    
    	void add(int u,int v) {e[++tot]=(edge){v,head[u]},head[u]=tot;}
    	void ins(int u,int v) {add(u,v),add(v,u);}
    	
    	void tarjan(int x,int fa) {
    		dfn[x]=low[x]=++dfn_cnt,sta[++top]=x;
    		for(int v,i=head[x];i;i=e[i].nxt) {
    			if((v=e[i].to)==fa) continue;
    			if(!dfn[v]) tarjan(v,x),low[x]=min(low[x],low[v]);
    			else low[x]=min(low[x],dfn[v]);
    		}
    		if(dfn[x]==low[x]) {
    			++col;
    			while(sta[top]!=x) bel[sta[top--]]=col;
    			bel[sta[top--]]=col;
    		}
    	}
    
    	void prepare() {
    		for(int i=1;i<=n;i++) if(!dfn[i]) tarjan(i,0);
    		for(int x=1;x<=n;x++)
    			for(int i=head[x];i;i=e[i].nxt)
    				if(bel[e[i].to]!=bel[x]) T.add(bel[e[i].to],bel[x]); //注意这里单向边
    		T.dfs(1,0);
    	}
    }G;
    
    int main() {
    	read(n),read(m);for(int i=1,x,y;i<=m;i++) read(x),read(y),G.ins(x,y);
    	G.prepare();int q;read(q);for(int i=1,x,y;i<=q;i++) read(x),read(y),write(T.dis(G.bel[x],G.bel[y]));
    	return 0;
    }
    
  • 相关阅读:
    linux常用命令
    windows 安装elasticsearch-head插件
    spring boot 使用logback日志系统的详细说明
    mysql 修改密码的几种方式
    html跑马灯效果
    windows 安装elk日志系统
    logstash 启动报找不主类或无法加载 java
    MySQL和Postgresql的区别
    Swift-----泛型Generic
    Swift-----扩展extension
  • 原文地址:https://www.cnblogs.com/hbyer/p/10613379.html
Copyright © 2011-2022 走看看