OJ-Problems-Source/HDOJ/4338_autoAC.cpp
2016-09-04 15:55:06 +08:00

187 lines
4.6 KiB
C++

#pragma comment(linker, "/STACK:102400000,102400000")
#include <algorithm>
#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <stack>
using namespace std;
const int N=200005;
#define Log 22
struct Edge
{
int v;
Edge *nxt;
}memo[N*10],*cur,*h_bef[N],*h_aft[N];
void addEdge(int u,int v,Edge* head[])
{
cur->v=v; cur->nxt=head[u];
head[u]=cur++;
}
int bnum,bn[N];
vector<int> block[N];
bool iscut[N];
bool vis[N];
stack<int> stk;
int dfn[N],low[N],son_root,idx;
int lab[N],id[N],son[N],fa[N];
int dp[N][Log],dep[N];
void tarjan(int pt_u,int pt_pre)
{
stack<int> stk_tar;
stk_tar.push(pt_u); fa[pt_u]=pt_pre;
while(stk_tar.size())
{
int u=stk_tar.top();
int pre=fa[u];
if(dfn[u]==0) dfn[u]=low[u]=++idx,stk.push(u);
Edge* it;
for(it=h_bef[u];it;it=it->nxt)
{
int v=it->v;
if(v==pre) continue;
if(fa[v]==-1)
{
fa[v]=u; stk_tar.push(v);
h_bef[u]=it;
break;
}
else
{
if(fa[v]==u)
{
low[u]=min(low[u],low[v]);
if(dfn[u]<=low[v])
{
if(pre==-1) son_root++;
else iscut[u]=1;
while(1)
{
int top=stk.top(); stk.pop();
block[bnum].push_back(top);
if(top==v) break;
}
block[bnum].push_back(u);
bnum++;
}
}
else low[u]=min(low[u],dfn[v]);
}
}
if(it==NULL) stk_tar.pop();
}
}
void dfs(int u,int pre,int cnt,int iid)
{
dep[u]=dep[ dp[u][0] ]+1;
for(int i=1;i<Log;i++) dp[u][i]= dp[ dp[u][i-1] ][ i-1 ];
id[u]=iid; son[u]=cnt+bn[u];
for(Edge* it=h_aft[u];it;it=it->nxt)
{
int v=it->v;
if(v!=pre)
{
dp[v][0]=u;
dfs(v,u,son[u],iid);
}
}
}
int lca(int u,int v)
{
if(dep[u]<dep[v]) swap(u,v);
for(int st=(1<<(Log-1)),i=Log-1;i>=0;st>>=1,i--)
{
if(st<=dep[u]-dep[v])
{
u=dp[u][i];
}
}
if(u==v) return u;
for(int i=Log-1;i>=0;i--)
{
if(dp[u][i]!=dp[v][i])
{
u=dp[u][i];
v=dp[v][i];
}
}
return dp[u][0];
}
void init()
{
cur=memo;
memset(h_bef,0,sizeof(h_bef));
memset(h_aft,0,sizeof(h_aft));
memset(dp,0,sizeof(dp));
bnum=0; idx=0; son_root=0;
while(stk.size()) stk.pop();
for(int i=0;i<N;i++)
{
block[i].clear();
dfn[i]=0; low[i]=0; lab[i]=-1;
id[i]=i; iscut[i]=0; bn[i]=0;
son[i]=0; dep[i]=0; vis[i]=0;
fa[i]=-1;
}
}
int main()
{
int n,m,Q,t_cnt=0;
while(scanf("%d%d",&n,&m)!=EOF)
{
init();
for(int i=0;i<m;i++)
{
int u,v; scanf("%d%d",&u,&v);
addEdge(u,v,h_bef);
addEdge(v,u,h_bef);
}
for(int i=0;i<n;i++) if(dfn[i]==0)
{
son_root=0;
tarjan(i,-2);
if(son_root>1) iscut[i]=1;
}
int k=0;
for(int i=0;i<n;i++) if(iscut[i])
{
lab[i]=k; bn[k]=1; k++;
}
for(int i=0;i<bnum;i++)
{
for(int j=0;j<(int)block[i].size();j++)
{
int u=block[i][j];
if(iscut[u])
{
addEdge(lab[u],k,h_aft);
addEdge(k,lab[u],h_aft);
}
else lab[u]=k;
}
bn[k]=(int)block[i].size();
k++;
}
for(int i=0;i<k;i++) if(dep[i]==0) dfs(i,-1,0,i);
scanf("%d",&Q);
printf("Case #%d:\n",++t_cnt);
while(Q--)
{
int s,t; scanf("%d%d",&s,&t);
if(s==t) printf("%d\n",n-1);
else if(lab[s]==-1||lab[t]==-1||id[lab[s]]!=id[lab[t]]) printf("%d\n",n);
else
{
s=lab[s]; t=lab[t];
int parent=lca(s,t);
int cnt=son[s]+son[t]-2*son[parent]+bn[parent];
int len=dep[s]+dep[t]-2*dep[parent];
int ans=cnt-len;
printf("%d\n",n-ans);
}
}
puts("");
}
return 0;
}