LuoGu P2783 有机化学之神偶尔会做作弊
题目传送门
人生第一道黑题呢,虽然这题是黑题中的水题并且我调了一整节课,但是我还是很兴奋啊.毕竟人生第一道黑题啊
这个题根据题意,先把整个图进行tarjan缩点,建出一棵树,对于每一组询问,两点之间的距离+1就是答案,求出他们的LCA,两点到LCA的距离之和就是两点之间的距离
然后....LCA我采用的是树剖方法,然后对于这个无向图中的强连通分量(其实是叫双连通分量),和有向图中强连通分量的求法并没有什么太大的差别
dfs时,注意不要让它走向父节点就好了
然后,,,,这题剩下的就是调试了
#include <iostream>
#include <cstdlib>
#include <cstdio>
#define min(a,b) (a<b?a:b)
using namespace std;
const int M=5e4+5;
const int N=1e4+5;
struct edge{
int to,next,pre;
}e[(M<<1)],t[(M<<1)];
int n,m,q,dfn[N],low[N],_top;
int siz[N],f[N],son[N],deep[N];
int head[N],tot,top[N],s[N],cnt;
int Tot,Head[N],total,idx[N],anc;
bool ins[N];
inline int read(){
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){
if(ch=='-') f=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9'){
x=x*10+ch-'0';
ch=getchar();
}
return x*f;
}
inline void build_edge(int u,int v){
e[++tot].next=head[u];head[u]=tot;
e[tot].to=v;e[tot].pre=v;return ;
}
inline void build_tree(int u,int v){
t[++Tot].next=Head[u];Head[u]=Tot;
t[Tot].to=v;t[Tot].pre=v;return ;
}
inline void tarjan(int cur,int anc){
s[++_top]=cur;dfn[cur]=low[cur]=++cnt;ins[cur]=true;
for(register int i=head[cur];i;i=e[i].next){
register int k=e[i].to;
if(k==anc) continue;
if(!dfn[k]){
tarjan(k,cur);
low[cur]=min(low[cur],low[k]);
}else if(ins[k]) low[cur]=min(low[cur],dfn[k]);
}
if(low[cur]==dfn[cur]){
++total;
while(s[_top+1]!=cur){
idx[s[_top]]=total;
ins[s[_top--]]=false;
}
}
return ;
}
inline void dfs1(int now,int anc,int dep){
deep[now]=dep;f[now]=anc;siz[now]=1;int maxson=-1;
for(register int i=Head[now];i;i=t[i].next){
register int k=t[i].to;if(k==anc) continue;
dfs1(k,now,dep+1);siz[now]+=siz[k];
if(siz[k]>maxson) maxson=siz[k],son[now]=k;
}
return ;
}
inline void dfs2(int now,int topf){
top[now]=topf;if(!son[now]) return ;dfs2(son[now],topf);
for(int i=Head[now];i;i=t[i].next){
int k=t[i].to;
if(k==f[now]||k==son[now]) continue;
dfs2(k,k);
}
return ;
}
inline int LCA(int x,int y){
while(top[x]!=top[y]){
if(deep[top[x]]<deep[top[y]]) y=f[top[y]];
else x=f[top[x]];
}
return (deep[x]<deep[y]?x:y);
}
inline void print(int x){
if(!x) return ;
print(x>>1);
printf("%d",x&1);
}
int main(){
n=read();m=read();
for(register int i=1;i<=m;++i){
register int u,v;
u=read();v=read();
build_edge(u,v);build_edge(v,u);
}
for(register int i=1;i<=n;++i) if(!dfn[i]) tarjan(i,0);
for(register int i=1;i<=n;++i)
for(register int j=head[i];j;j=e[j].next){
register int k=e[j].to;
if(idx[i]!=idx[k])
build_tree(idx[i],idx[k]);//build_tree(idx[k],idx[i]);
}
dfs1(1,0,1);dfs2(1,1);
q=read();
while(q--){
register int u=read(),v=read();
u=idx[u];v=idx[v];anc=LCA(u,v);
register int ans;
ans=deep[u]+deep[v]-(deep[anc]<<1)+1;
print(ans);printf("\n");
}
return 0;
}
LuoGu P2783 有机化学之神偶尔会做作弊的更多相关文章
- 【题解】Luogu P2783 有机化学之神偶尔会做作弊
原题链接:P2783 有机化学之神偶尔会做作弊 一看,是黑题,太毒瘤了,不写 什么单链??! 只会画有机化学中正六边形的我觉得这样不行QAQ(我才初二) 当然,题目也给你了详细的解释 实际呢,这道题先 ...
- luogu P2783 有机化学之神偶尔会做作弊 |Tarjan+LCA
题目背景 XS中学化学竞赛组教练是一个酷爱炉石的人. 有一天他一边搓炉石一边监考,而你作为一个信息竞赛的大神也来凑热闹. 然而你的化竞基友却向你求助了. "第1354题怎么做"&l ...
- 洛谷 P2783 有机化学之神偶尔会做作弊 解题报告
P2783 有机化学之神偶尔会做作弊 题目背景 XS中学化学竞赛组教练是一个酷爱炉石的人. 有一天他一边搓炉石一边监考,而你作为一个信息竞赛的大神也来凑热闹. 然而你的化竞基友却向你求助了. &quo ...
- 洛谷 P2783 有机化学之神偶尔会做作弊(Tarjan,LCA)
题目背景 LS中学化学竞赛组教练是一个酷爱炉石的人. 有一天他一边搓炉石一边监考,而你作为一个信息竞赛的大神也来凑热闹. 然而你的化竞基友却向你求助了. “第1354题怎么做”<--手语 他问道 ...
- [洛谷P2783]有机化学之神偶尔会做作弊
第一次做出来黑题祭 虽然感觉难度其实并不到黑题的难度 题解: 其实这道题并没用什么特别的知识,只是Tarjan求双联通分量和LCA的结合. 所以,我们可以很显然的发现(如此恶劣的词汇,逃 这道题其实就 ...
- Tarjan+LCA【洛谷P2783】 有机化学之神偶尔会做作弊
[洛谷P2783] 有机化学之神偶尔会做作弊 题目背景 XS中学化学竞赛组教练是一个酷爱炉石的人. 有一天他一边搓炉石一边监考,而你作为一个信息竞赛的大神也来凑热闹. 然而你的化竞基友却向你求助了. ...
- 【洛谷 P2783】 有机化学之神偶尔会做作弊 (双联通分量)
题目链接 可能是除了<概率论>的最水的黑题了吧 用\(Tarjan\)缩点(点双联通分量),然后就是树上两点之间的距离了,跑\(LCA\)就好了. #include <cstdio& ...
- Tarjan缩点+LCA【p2783】有机化学之神偶尔会做作弊
Description 你翻到那一题:给定一个烃,只含有单键(给初中生的一个理解性解释:就是一堆碳用横线连起来,横线都是单条的). 然后炎魔之王拉格纳罗斯用他的火焰净化了一切环(???).所有的环状碳 ...
- [luogu2783] 有机化学之神偶尔会做作弊
题目链接 洛谷. Solution 边双缩点然后\(lca\)跑\(dis\)就好了. 注意这里是边双,不知道为啥所有题解都说的是点双. 边双是定义在点上的,即每个点只属于一个边双:点双是定义在边上的 ...
随机推荐
- ****** 四十 ******、软设笔记【网络基础】-Internet和Intranet基础
Internet和Intranet基础 一.网络地址及子网掩码 1.IP地址结构及类别 IP地址是由32位二进制数,即4个字节组成的,由网络号和主机号两个字段组成. 网络号的位数决定了可以分配的网络数 ...
- nexys4ddr数码管动态扫描Verilog例程
题目:实现数码管动态扫描功能,将十六个开关的值以十六进制的方式在4个数码管上同时显示出来. `timescale 1ns / 1ps module top( clk, sw, seg, an ); / ...
- 【转】const int *p和int * const p的区别(常量指针与指向常量的指针)
[转]作者:xwdreamer 出处:http://www.cnblogs.com/xwdreamer 对于指针和常量,有以下三种形式都是正确的: const char * myPtr = &am ...
- springboot10-springcloud-eureka 服务注册与发现,负载均衡客户端(ribbon,feign)调用
创建5个项目: 1.服务注册中心 2.服务提供者1 3.服务提供者2(与服务提供者1的代码实现一样,这是是为了模拟负载均衡) 4.ribbon客户端项目 5.feign客户端项目 如图: 一.注册中心 ...
- springboot03-unittest mockmvc单元测试
整个项目结构: 定义user实体类 package com.mlxs.springboot.dto; import java.util.HashMap; import java.util.Map; / ...
- C# test
//测试对象集合序列化 public void jsonTest() { List<moduleEntity> list = new List<moduleEntity>(); ...
- MyList 泛型委托
using System; using System.Collections; using System.Collections.Generic; using System.Linq; using S ...
- Linux之文件恢复[extundelete,针对rm]
[恢复过程] 1.下载+安装extundelete cd /tmp wget wget http://jaist.dl.sourceforge.net/project/extundelete/extu ...
- JDK1.8HashMap源码解读
package java.util; import sun.misc.SharedSecrets; import java.io.IOException; import java.io.Invalid ...
- 异步Async
1.c#异步介绍 异步必须基于委托,有委托才有异步 新建一个window Form程序MyAsync,添加一个按钮,(name)=btnAsync 后台代码如下: using System;using ...