水60分
需要用到
一個叫橋的東西
這個橋是什麼呢?
就是一條很重要的邊,你把這條邊去掉之後整個圖就不連通了
接下來就可以發現,一張圖的橋將這張圖分成了一棵樹
這棵樹上的節點對應的是一個一個連通塊
每一個連通塊內的點到另一個連通塊內的點之間的關鍵路徑的條數
即爲兩個點之間橋的個數,也即爲兩個連通塊在樹上的路徑
那麼我們可以將原問題轉化成求用橋構成的樹上兩點之間的距離了
那麼
怎麼求橋呢?怎麼將原圖用橋分開呢?
我們對原圖進行一次dfs,在這過程中記錄兩個東西
dfn[i]:表示i的dfs序,即在dfs過程中被遍歷到的順序
low[i]:表示i能夠連接到的最小的祖先,即i能夠到達的已經被dfs過的dfs序最小的點
橋的判定:
如果對於一條邊(u,v)
有
有了這個性質可以在dfs過程中求出橋了
求出橋之後,再考慮構建樹邊
如果把所有的橋全部拿走的話
可以看見整個圖被分成了互不相連的好幾個連通塊
可以把這些連通塊縮成樹上的一個點
然後再把橋邊放回去,構成樹邊
建完樹之後就可以利用樹上lca的知識來求樹上兩點之間的距離了
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<vector>
#include<cstring>
#include<cctype>
using namespace std;
const int MAXN=3e4+2,MAXE=1e5+2,S=20;
inline void Rd(int &res){
char c;res=0;
while(c=getchar(),!isdigit(c));
do res=(res<<3)+(res<<1)+(c^48);
while(c=getchar(),isdigit(c));
}
struct Edge{
int to,nxt;
}edge[MAXE];
int n,m,Q;
int head[MAXN],tot;
int e[MAXN][2];
int belongto[MAXN];
int isbridge[MAXN];
int dfn[MAXN],low[MAXN],T,bcnt;
vector<int>tree[MAXN];
int fa[MAXN][S],dep[MAXN];
inline void add(int a,int b){
edge[tot].to=b;edge[tot].nxt=head[a];head[a]=tot++;
}
void dfs(int x,int f){
dfn[x]=low[x]=++T;
for(int i=head[x];~i;i=edge[i].nxt){
int y=edge[i].to;
if(y==f)continue;
if(dfn[y]==0){
dfs(y,x);
if(low[y]>dfn[x])isbridge[i]=1,isbridge[i^1]=1;
else low[x]=min(low[x],low[y]);
}else low[x]=min(low[x],dfn[y]);
}
}
void setID(int x){
belongto[x]=bcnt;
for(int i=head[x];~i;i=edge[i].nxt){
if(isbridge[i]||belongto[edge[i].to])continue;
setID(edge[i].to);
}
}
void Tdfs(int now,int pre,int Dep){
fa[now][0]=pre;dep[now]=Dep;
for(int i=0;i<tree[now].size();i++){
int nxt=tree[now][i];
if(nxt==pre)continue;
Tdfs(nxt,now,Dep+1);
}
}
inline void init(){
for(int j=1;(1<<j)<n;j++)
for(int i=1;i<=n;i++)
fa[i][j]=fa[fa[i][j-1]][j-1];
}
inline void up(int &a,int step){
for(int i=0;i<S;i++)
if(step&(1<<i))
a=fa[a][i];
}
int LCA(int a,int b){
if(dep[a]>dep[b])swap(a,b);
up(b,dep[b]-dep[a]);
if(a!=b){
for(int i=S-1;i>=0;i--)
if(fa[a][i]!=fa[b][i])
a=fa[a][i],b=fa[b][i];
a=fa[a][0];
}return a;
}
int main(){
memset(head,-1,sizeof(head));tot=0;
Rd(n),Rd(m),Rd(Q);
int a,b,type;
for(int i=0;i<m;i++){
Rd(a),Rd(b);
add(a,b);add(b,a);
e[i][0]=a;e[i][1]=b;
}
dfs(1,0);
for(int i=1;i<=n;i++)
if(!belongto[i]){
bcnt++;
setID(i);
}
for(int i=0;i<m;i++){
int a=belongto[e[i][0]],b=belongto[e[i][1]];
if(a==b)continue;
tree[a].push_back(b);
tree[b].push_back(a);
}
Tdfs(1,0,1);
init();
while(Q--){
Rd(type),Rd(a),Rd(b);
a=belongto[a];b=belongto[b];
int lca=LCA(a,b);
printf("%d\n",dep[a]+dep[b]-2*dep[lca]);
}
return 0;
}