[luogu2783] 有機化學之神偶爾會做作弊
阿新 • • 發佈:2019-03-28
name graph dep https define pre write code oid
題目鏈接
洛谷.
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('\n');} #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; }
[luogu2783] 有機化學之神偶爾會做作弊