[luogu p2783]有机化学之神 (最水黑题)
Posted djhsbdb
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[luogu p2783]有机化学之神 (最水黑题)相关的知识,希望对你有一定的参考价值。
题目背景
XS中学化学竞赛组教练是一个酷爱炉石的人。
有一天他一边搓炉石一边监考,而你作为一个信息竞赛的大神也来凑热闹。
然而你的化竞基友却向你求助了。
“第1354题怎么做”<--手语 他问道。
题目描述
你翻到那一题:给定一个烃,只含有单键(给初中生的一个理解性解释:就是一堆碳用横线连起来,横线都是单条的)。
然后炎魔之王拉格纳罗斯用他的火焰净化了一切环(???)。所有的环状碳都变成了一个碳。如图所示。
然后指定多组碳,求出它们之间总共有多少碳。如图所示(和上图没有关系)。
但是因为在考试,所以你只能把这个答案用手语告诉你的基友。你决定用二进制来表示最后的答案。如图所示(不要在意,和题目没有什么没关系)。
输入输出格式
输入格式:
第一行两个整数n,m.表示有n个点,m根键
接下来m行每行两个整数u,v表示u号碳和v号碳有一根键
接下来一个整数tot表示询问次数
接下来tot行每行两个整数,a,b表示询问的两个碳的编号
输出格式:
共tot行
每行一个二进制数
输入输出样例
输出样例:
10 10
双连通分量+lca求距离
不知道为什么是黑题,连我这种小蒟蒻都会的。。
主要是tarjan和lca求距离以及缩点重建图
直接上代码
#include<iostream> #include<cstdio> #include<cstring> #include<queue> #include<algorithm> #include<cmath> #include<vector> #include<stack> using namespace std; inline int read(){ int x=0; bool f=1; char c=getchar(); while(!isdigit(c)){if(c==‘-‘)f=0;c=getchar();} while(isdigit(c)){x=x*10+c-‘0‘;c=getchar();} if(!f)return 0-x; return x; } const int M=10010; const int N=50010; vector<int>e[M];//无权图,直接存vector vector<int>g[M]; int n,m,tot,dfn[M],low[M],vis[M],color[M],tim,megumi,x[N],y[N],f[M][25],depth[M],QAQ; stack<int>s; inline void tarjan(int u,int fa){ dfn[u]=low[u]=++tim; s.push(u); for(int i=0;i<e[u].size();i++){ int v=e[u][i]; if(v==fa)continue;//双连通分量 if(!dfn[v]){ tarjan(v,u); low[u]=min(low[u],low[v]); } else if(!color[v]) low[u]=min(low[u],dfn[v]); } if(low[u]==dfn[u]){ ++megumi; while(s.top()!=u){ color[s.top()]=megumi; s.pop(); } color[s.top()]=megumi; s.pop(); } } inline void rebuild(){ for(int i=1;i<=m;i++){ if(color[x[i]]^color[y[i]]) g[color[x[i]]].push_back(color[y[i]]),g[color[y[i]]].push_back(color[x[i]]);//必须是color[x[i]],卡了半个小时qwq } } inline void dfs(int u,int fa){ if(vis[u])return ; vis[u]=1; depth[u]=depth[fa]+1; for(int i=1;i<=20;i++){ f[u][i]=f[f[u][i-1]][i-1]; } for(int i=0;i<g[u].size();i++){ int v=g[u][i]; if(v==fa)continue; f[v][0]=u; dfs(v,u); } } inline int lca(int a,int b){ if(depth[a]<depth[b]) swap(a,b); for(int i=20;i>=0;i--){ if(depth[f[a][i]]>=depth[b]) a=f[a][i]; } if(a==b)return a; for(int i=20;i>=0;i--){ if(f[a][i]!=f[b][i]){ a=f[a][i],b=f[b][i]; } } return f[a][0]; } inline void print(int x){//打印二进制 if(!x)return ; print(x>>1); printf("%d",x&1); } int main(){ // freopen("haha.in","r",stdin); n=read(),m=read(); for(int i=1;i<=m;i++){ x[i]=read(),y[i]=read(); e[x[i]].push_back(y[i]); e[y[i]].push_back(x[i]); } for(int i=1;i<=n;i++){ if(!dfn[i])tarjan(i,i); } rebuild(); megumi++; for(int i=1;i^megumi;i++){ if(!vis[i])dfs(i,i); } tot=read(); for(int i=1;i<=tot;i++){ int x,y; x=read(),y=read(); int l=lca(color[x],color[y]); print(depth[color[x]]-depth[l]+depth[color[y]]-depth[l]+1); printf(" "); } // fclose(stdin); return QAQ; }
以上是关于[luogu p2783]有机化学之神 (最水黑题)的主要内容,如果未能解决你的问题,请参考以下文章