博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【洛谷 P2783】 有机化学之神偶尔会做作弊 (双联通分量)
阅读量:6238 次
发布时间:2019-06-22

本文共 2537 字,大约阅读时间需要 8 分钟。

可能是除了《概率论》的最水的黑题了吧
\(Tarjan\)缩点(点双联通分量),然后就是树上两点之间的距离了,跑\(LCA\)就好了。

#include 
#include
#include
using namespace std;int s; char ch;inline int read(){ s = 0; ch = getchar(); while(ch < '0' || ch > '9') ch = getchar(); while(ch >= '0' && ch <= '9') { s = s * 10 + ch - '0'; ch = getchar(); } return s;}const int MAXN = 10010;const int MAXM = 50010;int dfn[MAXN], low[MAXN], id, bridge[MAXM << 1], dcc, belong[MAXN], top, vis[MAXN];int n, m, a, b, head[MAXN], num = 1, f[MAXN][20], dep[MAXN], t, stack[MAXN];struct Edge{ int from, next, to;}e[MAXM << 2];inline void Add(int from, int to){ e[++num].to = to; e[num].from = from; e[num].next = head[from]; head[from] = num; e[++num].to = from; e[num].from = to; e[num].next = head[to]; head[to] = num;}void Tarjan(int u, int fa){ dfn[u] = low[u] = ++id; stack[++top] = u; vis[u] = 1; for(int i = head[u]; i; i = e[i].next) if(e[i].to != fa) if(!dfn[e[i].to]){ Tarjan(e[i].to, u); low[u] = min(low[u], low[e[i].to]); } else if(vis[e[i].to]) low[u] = min(low[u], dfn[e[i].to]); if(dfn[u] == low[u]){ ++dcc; do belong[stack[top]] = dcc; while(stack[top--] != u); }}void getDF(int u, int fa){ f[u][0] = fa; dep[u] = dep[fa] + 1; for(int i = head[u]; i; i = e[i].next) if(e[i].to != fa) getDF(e[i].to, u);}int LCA(int u, int v){ if(dep[u] < dep[v]) swap(u, v); int cha = dep[u] - dep[v]; if(cha) for(int i = 0; i <= 18; ++i) if((cha >> i) & 1) u = f[u][i]; if(u != v){ for(int i = 18; ~i; --i) if(f[u][i] != f[v][i]) u = f[u][i], v = f[v][i]; return f[u][0]; } return u;}int dis(int u, int v){ return dep[u] + dep[v] - (dep[LCA(u, v)] << 1) + 1;}void print(int x){ if(x > 1) print(x >> 1); printf("%d", x & 1);}int main(){ n = read(); m = read(); for(int i = 1; i <= m; ++i) Add(read(), read()); for(int i = 1; i <= n; ++i) if(!dfn[i]) Tarjan(i, 0); memset(head, 0, sizeof head); int tmp = num; for(int i = 2; i <= tmp; i += 2) if(belong[e[i].from] != belong[e[i].to]) Add(belong[e[i].from], belong[e[i].to]); getDF(1, 0); for(int j = 1; j <= 18; ++j) for(int i = 1; i <= dcc; ++i) f[i][j] = f[f[i][j - 1]][j - 1]; t = read(); while(t--) print(dis(belong[read()], belong[read()])), puts(""); return 0;}

转载于:https://www.cnblogs.com/Qihoo360/p/9754672.html

你可能感兴趣的文章
将字符序列用其反转形式取代
查看>>
在Eclipse中制作和使用struts2配置文件提示插件
查看>>
操作系统
查看>>
从需求向设计转化的密码
查看>>
360浏览器极速模式pdf文件不能预览问题
查看>>
CAS:PKIX path building failed
查看>>
测试php与mysql的连接是否成功的多种方法
查看>>
15条SQLite3数据库常用语句
查看>>
二叉树中找两个结点的最近的公共祖先结点
查看>>
Mac下sqlite3的学习总结
查看>>
基本配置实验
查看>>
使用适合的质量工具
查看>>
Linux 必学和要掌握的路径
查看>>
WBS分解
查看>>
centos5.6安装FTP
查看>>
http-equiv,很强大
查看>>
安装字体与ubuntu-tweak
查看>>
平均值方法:Avg API-Medoo使用指南
查看>>
centos6,7没有安装ifconfig命令的解决方法
查看>>
web页面禁用右键、禁用左键、禁止查看源代码、禁用触摸板
查看>>