题目背景
XS中学化学竞赛组教练是一个酷爱炉石的人。
有一天他一边搓炉石一边监考,而你作为一个信息竞赛的大神也来凑热闹。
然而你的化竞基友却向你求助了。
“第1354题怎么做”<–手语 他问道。
题目描述
你翻到那一题:给定一个烃,只含有单键(给初中生的一个理解性解释:就是一堆碳用横线连起来,横线都是单条的)。
然后炎魔之王拉格纳罗斯用他的火焰净化了一切环(???)。所有的环状碳都变成了一个碳。如图所示。
然后指定多组碳,求出它们之间总共有多少碳。如图所示(和上图没有关系)。
但是因为在考试,所以你只能把这个答案用手语告诉你的基友。你决定用二进制来表示最后的答案。如图所示(不要在意,和题目没有什么没关系)。
输入输出格式
输入格式:
第一行两个整数n,m.表示有n个点,m根键
接下来m行每行两个整数u,v表示u号碳和v号碳有一根键
接下来一个整数tot表示询问次数
接下来tot行每行两个整数,a,b表示询问的两个碳的编号
输出格式:
共tot行
每行一个二进制数
输入输出样例
输入样例#1:
3 2
1 2
2 3
2
1 2
2 3
输出样例#1:
10
10
说明
1
//居然忘记发题解了,八月多A掉的一道题,到现在有人问我,才..
#include<iostream>
#include<cstring>
#include<cstdio>
#include<queue>
#include<stack>
using namespace std;
#define MAXN 10010
#define MAXM 100010
int head[MAXN],dfn[MAXN],low[MAXN],visx,link[MAXN],tot,fa[MAXN][25];
int belong[MAXN],m,n,tot_,dep[MAXN],xx[MAXM],yy[MAXM];
bool exist[MAXN];
stack<int> st;
struct Edge{ int to,next; }e[MAXM*2],ee[MAXM*2];
inline int read(int &x){
x=0;char c=getchar();
while(c>'9'||c<'0') c=getchar();
while(c>='0'&&c<='9'){ x=x*10+c-'0';c=getchar(); }
}
inline void Add_Edge(int u,int v){
e[++tot].to=v;e[tot].next=head[u];head[u]=tot;
}
int cnt;
void Tarjan(int u,int from){
low[u]=dfn[u]= ++visx; st.push(u); exist[u]=true;
for(int i=head[u];i;i=e[i].next){
int v=e[i].to;
if(v==from) continue;
if(dfn[v]==-1) Tarjan(v,u),low[u]=min(low[u],low[v]);
else if(exist[v]) low[u]=min(low[u],dfn[v]);
}
if(dfn[u]==low[u]){
++cnt;
while(1){
int v=st.top();st.pop();
exist[v]=0; belong[v]=cnt;
if(v==u) break;
}
}
}
inline void Add_Edge_(int u,int v){
ee[++tot_].to=v;ee[tot_].next=link[u];link[u]=tot_;
}
void Make_New(){
for(int i=1;i<=m;i++){
if(belong[xx[i]]!=belong[yy[i]]){
Add_Edge_(belong[xx[i]],belong[yy[i]]);
Add_Edge_(belong[yy[i]],belong[xx[i]]);
}
}
}
void Get_Fa(){
for(int j=1;j<=22;j++)
for(int i=1;i<=cnt;i++)
fa[i][j]=fa[fa[i][j-1]][j-1];
}
void DFS(int u,int from,int deepth){
dep[u]=deepth; fa[u][0]=from;
for(int i=link[u];i;i=ee[i].next){
int v=ee[i].to;
if(v!=from) DFS(v,u,deepth+1);
}
}
int LCA(int u,int v){
if(dep[u]<dep[v]) swap(u,v);
for(int j=0;j<=22;j++)
if((dep[u]-dep[v])&(1<<j)) u=fa[u][j];
if(u==v) return u;
for(int i=22;i>=0;i--)
if(fa[u][i]!=fa[v][i]){
u=fa[u][i],v=fa[v][i];
}
return fa[u][0];
}
int ans[28000];
int change(int n){
int cur=0;
if(n==0){ cout<<'0';return 0; }
if(n<0) { putchar('-');n=0-n; }
while(n){
int p=n%2;ans[++cur]=p;
n/=2;
}
for(int i=cur;i>=1;i--) printf("%d",ans[i]);
cout<<endl;
}
int main(){
read(n);read(m);
memset(dfn,-1,sizeof dfn );
memset(low,-1,sizeof low );
for(int u,v,i=1;i<=m;i++){
read(u),read(v);
xx[i]=u,yy[i]=v;
Add_Edge(u,v),Add_Edge(v,u);
}
for(int i=1;i<=n;i++)
if(dfn[i]==-1)
Tarjan(i,-1);
Make_New();
DFS(belong[1],belong[1],0);
Get_Fa();
int T;
read(T);
while(T--){
int u,v;
scanf("%d%d",&u,&v);
int ans=LCA(belong[u],belong[v]);
change(dep[belong[u]]+dep[belong[v]]-dep[ans]-dep[ans]+1);
//printf("%d\n",dep[belong[u]]+dep[belong[v]]-dep[ans]-dep[ans]+1);
}
return 0;
}
/*
6 5
1 2
2 3
3 4
1 5
5 6
1
4 6
*/