题目链接

可能是除了《概率论》的最水的黑题了吧

用\(Tarjan\)缩点(点双联通分量),然后就是树上两点之间的距离了,跑\(LCA\)就好了。

#include <cstdio>
#include <cstring>
#include <algorithm>
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;
}

最新文章

  1. chrome经常崩溃解决过程
  2. Java Se :线性表
  3. Jmeter组件4. Regular Expression Extractor
  4. TeeChart中 Line的Clear方法
  5. 微信 关闭手机微信内置浏览器的js
  6. ios 7 20像素解决
  7. 调试技巧 —— 如何利用windbg + dump + map分析程序异常
  8. 通过PHP连接MYSQL数据库 创建数据库 创建表
  9. IE 将“通过域访问数据源”设置为启用(注册表)
  10. mysql在linux的安装
  11. 输入一个数字n 如果n为偶数则除以2,若为奇数则加1或者减1,直到n为1,求最少次数 写出一个函数
  12. Tornado 网站demo 一
  13. shell 排除目录
  14. JS学习小结(上)
  15. Codeforces 868D Huge Strings - 位运算 - 暴力
  16. linux中eth0原何变成了eth1
  17. 绕过限制,在PC上调试微信手机页面
  18. Token机制,防止web页面重复提交
  19. sklearn 中的交叉验证
  20. history统计命令最多的20条

热门文章

  1. LintCode-66.二叉树的前序遍历
  2. TCP系列25—重传—15、DSACK虚假重传探测
  3. SQL SERVER技术内幕之10 可编程对象
  4. C#中Console.ReadLine()和Console.Read()有何区别?
  5. Flink中的数据传输与背压
  6. centos7 nginx端口转发出现502的其中一种原因
  7. BZOJ 1022 小约翰的游戏(anti-sg)
  8. P2845 [USACO15DEC]Switching on the Lights 开关灯
  9. 【以前的空间】BIT的两个小小运用
  10. 运动员最佳匹配问题 KM算法:带权二分图匹配