题目背景

LS中学化学竞赛组教练是一个酷爱炉石的人。

有一天他一边搓炉石一边监考,而你作为一个信息竞赛的大神也来凑热闹。

然而你的化竞基友却向你求助了。

“第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<n<=10000,1<m<=50000

(两个碳不成环)

这是一道包含了两个板子的题目:tarjan+lca。(应该还是比较明显的)

但是这里我们发现C与C之间必须要连一条双向边,不符合普通tarjan的要求。

我们注意到题目中的条件:两个C不成环。那我们只要让当前的点不递归到它的"爸爸"就可以了。

lca是在树上求两点距离的很常见,常用的办法,在碰到树上题目是可以多考虑。

至于2进制我打的不是很简洁,可以学习一下别人的。

 #include<bits/stdc++.h>
using namespace std;
int n,m,cnt,vistime,sum,top;
int head[],h[],dfn[],low[],s[],num[],deep[],f[][],belong[],ans[];
bool instack[];
struct node{
int to,next;
}edge[],e[];
int read()
{
int x=,w=;char ch=getchar();
while(ch>''||ch<'') {if(ch=='-')w=-;ch=getchar();}
while(ch>=''&&ch<='') x=(x<<)+(x<<)+ch-'',ch=getchar();
return x*w;
}
void add(int x,int y)
{
cnt++;
edge[cnt].to=y;
edge[cnt].next=head[x];
head[x]=cnt;
}
void ad(int x,int y)
{
cnt++;
e[cnt].to=y;
e[cnt].next=h[x];
h[x]=cnt;
}
void print(int x)
{
int cnt=;
if(x==) {printf("");return;}
if(x<) printf("-"),x=-x;
while(x)
{
cnt++;
if(x&) ans[cnt]=;
x>>=;
}
for(int i=cnt;i>;i--)
{
printf("%d",ans[i]);
ans[i]=;
}
printf("\n");
}
void tarjan(int,int);
void build(int,int,int);
int lca(int,int);
int main()
{
int u,v,tot;
n=read();m=read();
for(int i=;i<=m;i++)
{
u=read();v=read();
add(u,v);
add(v,u);
}
cnt=;
for(int i=;i<=n;i++)
{
if(!dfn[i])
tarjan(i,);
}
for(int i=;i<=n;i++)
{
for(int j=head[i];j;j=edge[j].next)
{
v=edge[j].to;
if(belong[v]!=belong[i])
{
ad(belong[i],belong[v]);
}
}
}
build(,,);
for(int j=;j<=;j++)
for(int i=;i<=sum;i++)
{
f[i][j]=f[f[i][j-]][j-];
}
tot=read();
for(int i=;i<=tot;i++)
{
u=read();v=read();
int LCA=lca(belong[u],belong[v]);
print(deep[belong[u]]+deep[belong[v]]-*deep[LCA]+);
}
}
void tarjan(int u,int from)//增加参数,防止搜回去
{
int v;
dfn[u]=low[u]=++vistime;
s[++top]=u;
instack[u]=true;
for(int i=head[u];i;i=edge[i].next)
{
v=edge[i].to;
if(v==from) continue;
if(!dfn[v])
{
tarjan(v,u);
low[u]=min(low[v],low[u]);
}
else if(instack[v])
{
low[u]=min(low[u],dfn[v]);
}
}
if(dfn[u]==low[u])
{
sum++;
do
{
v=s[top--];
belong[v]=sum;
num[sum]++;
instack[v]=false;
}while(u!=v);
}
}
void build(int k,int fa,int d)
{
int v;
deep[k]=d;
for(int i=h[k];i;i=e[i].next)
{
v=e[i].to;
if(v!=fa&&!deep[v])
{
f[v][]=k;
build(v,k,d+);
}
}
}
int lca(int x,int y)
{
if(deep[x]>deep[y]) swap(x,y);
for(int i=;i>=;i--)
if(deep[f[y][i]]>=deep[x]) y=f[y][i];
if(x==y) return x;
for(int i=;i>=;i--)
{
if(f[x][i]!=f[y][i])
x=f[x][i],y=f[y][i];
}
return f[x][];
}

洛谷 P2783 有机化学之神偶尔会做作弊(Tarjan,LCA)的更多相关文章

  1. 洛谷 P2783 有机化学之神偶尔会做作弊 解题报告

    P2783 有机化学之神偶尔会做作弊 题目背景 XS中学化学竞赛组教练是一个酷爱炉石的人. 有一天他一边搓炉石一边监考,而你作为一个信息竞赛的大神也来凑热闹. 然而你的化竞基友却向你求助了. &quo ...

  2. [洛谷P2783]有机化学之神偶尔会做作弊

    第一次做出来黑题祭 虽然感觉难度其实并不到黑题的难度 题解: 其实这道题并没用什么特别的知识,只是Tarjan求双联通分量和LCA的结合. 所以,我们可以很显然的发现(如此恶劣的词汇,逃 这道题其实就 ...

  3. luogu P2783 有机化学之神偶尔会做作弊 |Tarjan+LCA

    题目背景 XS中学化学竞赛组教练是一个酷爱炉石的人. 有一天他一边搓炉石一边监考,而你作为一个信息竞赛的大神也来凑热闹. 然而你的化竞基友却向你求助了. "第1354题怎么做"&l ...

  4. 【题解】Luogu P2783 有机化学之神偶尔会做作弊

    原题链接:P2783 有机化学之神偶尔会做作弊 一看,是黑题,太毒瘤了,不写 什么单链??! 只会画有机化学中正六边形的我觉得这样不行QAQ(我才初二) 当然,题目也给你了详细的解释 实际呢,这道题先 ...

  5. 洛谷P2783 有机化学之神偶尔会作弊

    题目传送门 啦啦啦,发个文纪念一下第一道在洛谷上A的黑题,一次性就过真是无比舒服-(虽然某些大佬说这题有点水……)题目其实思路不难,Tarjan缩点+LCA,不过因为是无向边,所以在Tarjan的时候 ...

  6. LuoGu P2783 有机化学之神偶尔会做作弊

    题目传送门 人生第一道黑题呢,虽然这题是黑题中的水题并且我调了一整节课,但是我还是很兴奋啊.毕竟人生第一道黑题啊 这个题根据题意,先把整个图进行tarjan缩点,建出一棵树,对于每一组询问,两点之间的 ...

  7. Tarjan+LCA【洛谷P2783】 有机化学之神偶尔会做作弊

    [洛谷P2783] 有机化学之神偶尔会做作弊 题目背景 XS中学化学竞赛组教练是一个酷爱炉石的人. 有一天他一边搓炉石一边监考,而你作为一个信息竞赛的大神也来凑热闹. 然而你的化竞基友却向你求助了. ...

  8. [luogu2783] 有机化学之神偶尔会做作弊

    题目链接 洛谷. Solution 边双缩点然后\(lca\)跑\(dis\)就好了. 注意这里是边双,不知道为啥所有题解都说的是点双. 边双是定义在点上的,即每个点只属于一个边双:点双是定义在边上的 ...

  9. 【洛谷 P2783】 有机化学之神偶尔会做作弊 (双联通分量)

    题目链接 可能是除了<概率论>的最水的黑题了吧 用\(Tarjan\)缩点(点双联通分量),然后就是树上两点之间的距离了,跑\(LCA\)就好了. #include <cstdio& ...

随机推荐

  1. sql server 高版本数据还原到低版本sql server的注意事项

    生成的sql脚本不能大于100m,否则会报错(System.OutOfMemory) 所以要将较大的sql脚本文件进行分割

  2. Springboot-H2DB

    为什么在Springboot中用H2DB 用Springboot开发需要连接数据库的程序的时候,使用H2DB作为内存数据库可以很方便的调试程序. 怎么用 1.加入依赖 <dependency&g ...

  3. SpringMVC常用方法总结

    *) @RequestMapping(value="/xxx/{id}",method={RequestMethod.GET}) method 不写的话,默认GET.POST都支持 ...

  4. 安装完Fedora 18后需要做的事情

    折腾了好久,在网上查看了好多资料,总算吧安装好的Fedora 18配置得差不多了,现在将过程记录下来,供以后查看用,同时也许还能帮助到和我遇到同一问题的朋友们,以后再有什么再继续添加吧. 一.添加 y ...

  5. 第三方框架:EventBus

    1 研发背景 案例:我们在主页点收藏按钮,未登录状态,跳登录界面,在登录界面跳注册页面,注册成功,关闭注册页面,关闭登录页面,回到主页,刷新item列表和登录状态. 我们一般会用到发送广播和接收广播来 ...

  6. day63—JavaScript浏览器对象cookie

    转行学开发,代码100天——2018-05-18 今天的主要学内容时JavaScript中浏览器对象——cookie. cookie用于存储web页面的用户信息,其存储容量很小,一般几k左右.如常见的 ...

  7. 010-Spring Boot 扩展分析-ApplicationContextInitializer、CommandLineRunner、ApplicationRunner

    一.常见的两个扩展点 1.ApplicationContextInitializer 1.1.作用实现 作用:接口实在Spring容器执行refresh之前的一个回调. Callback interf ...

  8. 阶段1 语言基础+高级_1-3-Java语言高级_1-常用API_1_第4节 ArrayList集合_17-ArrayList练习二_存储自定义

    分析题目和解题思路 先来新建学生类.定义两个成员变量,后面进行代码的生成 遍历集合

  9. mac, ios 模拟器

    genymotion  最好的android 硬件模拟器. 可多开,可gps定位,可模拟重力系统,可模拟磁场系统,模拟器海拔高度. 甚至可以模拟sd卡. 直接就等于真机. virtualbox 最好的 ...

  10. 06 使用bbed修复delete的数据--01

    06 使用bbed修复delete的数据--01 根据rowid查看数据文件和block号 SYS@ orcl ; ROWID ID NAME FILE# BLOCK# --------------- ...