题面

思路

考场想到 \(tarjan\) 缩点

然而忘了缩点怎么打

于是甩了个暴力

改题时学了个圆方树

发现挺好用

于是······注意重边

\(Code\)

#include<cstdio>
#include<iostream>
#include<cmath>
#include<map>
using namespace std; const int N = 3e5 + 5;
int n , m , q , cnt , tot1 , tot2 , top , dfc;
int p[N][2] , h1[N] , h2[N] , dfn[N] , low[N] , df[N] , f[N][22] , fa[N][22] , dep[N];
map<pair<int , int> , int> mp; struct edge1{
int nxt , to , w;
}e1[N * 2];
struct edge2{
int nxt , to , w;
}e2[N * 2];
struct node{
int x , z;
}stack[N]; void add1(int x , int y , int z)
{
e1[++tot1] = edge1{h1[x] , y , z};
h1[x] = tot1;
}
void add2(int x , int y , int z)
{
e2[++tot2] = edge2{h2[x] , y , z};
h2[x] = tot2;
} void tarjan(int x , int fa , int z)
{
stack[++top] = node{x , z};
low[x] = dfn[x] = ++dfc;
for(register int i = h1[x]; i; i = e1[i].nxt)
{
int v = e1[i].to;
if (!dfn[v])
{
tarjan(v , x , e1[i].w) , low[x] = min(low[x] , low[v]);
if (dfn[x] < low[v]) add2(x , v , e1[i].w) , df[v] = e1[i].w , --top;
else if (dfn[x] == low[v])
{
int BBC = 0 , tp = top;
for(register int j = h1[x]; j; j = e1[j].nxt)
if (e1[j].to == stack[top].x){BBC = e1[j].w; break;}
add2(x , ++cnt , 0);
while (stack[tp].x != x) df[stack[tp].x] = BBC , BBC += stack[tp].z , --tp;
while (stack[top].x != x)
add2(cnt , stack[top].x , min(df[stack[top].x] , BBC - df[stack[top].x])) , --top;
df[cnt] = BBC;
}
}
else if (v != fa) low[x] = min(low[x] , dfn[v]);
}
} void dfs(int x , int d)
{
dep[x] = d;
for(register int i = 1; i <= 20; i++)
if (fa[x][i - 1]) fa[x][i] = fa[fa[x][i - 1]][i - 1] , f[x][i] = f[x][i - 1] + f[fa[x][i - 1]][i - 1];
else break;
for(register int i = h2[x]; i; i = e2[i].nxt)
{
fa[e2[i].to][0] = x , f[e2[i].to][0] = e2[i].w;
dfs(e2[i].to , d + 1);
}
} int getans(int x , int y)
{
int u = x , v = y;
if (dep[u] < dep[v]) swap(u , v);
int deep = dep[u] - dep[v] , res = 0;
for(register int i = 0; i <= 20; i++)
if (deep & (1 << i)) res += f[u][i] , u = fa[u][i];
if (u == v) return res;
for(register int i = 20; i >= 0; i--)
if (fa[u][i] != fa[v][i]) res += f[u][i] + f[v][i] , u = fa[u][i] , v = fa[v][i];
if (fa[u][0] <= n) return res + f[u][0] + f[v][0];
return res + min(abs(df[u] - df[v]) , df[fa[u][0]] - abs(df[u] - df[v]));
} int main()
{
freopen("garden.in" , "r" , stdin);
freopen("garden.out" , "w" , stdout);
scanf("%d%d" , &n , &m);
int x , y , z;
for(register int i = 1; i <= m; i++)
{
scanf("%d%d%d" , &x , &y , &z);
if (x > y) swap(x , y);
p[i][0] = x , p[i][1] = y;
if (mp[make_pair(x , y)] == 0) mp[make_pair(x , y)] = z;
else mp[make_pair(x , y)] = min(mp[make_pair(x , y)] , z);
}
for(register int i = 1; i <= m; i++)
{
x = p[i][0] , y = p[i][1] , z = mp[make_pair(x , y)];
add1(x , y , z) , add1(y , x , z);
}
cnt = n;
tarjan(1 , 0 , 0);
dfs(1 , 0);
scanf("%d" , &q);
for(register int i = 1; i <= q; i++)
{
scanf("%d%d" , &x , &y);
printf("%d\n" , getans(x , y));
}
}

最新文章

  1. springmvc+mybatis+spring 整合源码项目
  2. Linux进程间通信(七):消息队列 msgget()、msgsend()、msgrcv()、msgctl()
  3. PHP Log时时查看小工具
  4. 检查点(Checkpoint)过程如何处理未提交的事务
  5. Android jni开发中的常见错误
  6. linux根目录下文件夹概览
  7. 在Windows下部署安装hexo
  8. mysql 存储过程 demo
  9. Metro 应用无法打开解决办法
  10. (转载)腾讯CMEM的PHP扩展
  11. 在Cocos2d-x正在使用SQLlite数据库
  12. RabbitMQ 入门【精+转】
  13. 浅谈AndroidGPU过度绘制、GPU呈现模式分析及相关优化
  14. DSAPI之摄像头追踪指定颜色物体
  15. Camp 前三日简单总结
  16. Laravel 项目中使用 Bootstrap 框架
  17. SAP MM/FI 自动过账实现 OBYC 接口执行
  18. OpenStack trove原理及配置实践
  19. The superclass &quot;javax.servlet.http.HttpServlet&quot; was not found on the Java Build Path 解决方法
  20. java反射机制学习代码

热门文章

  1. 《MySQL必知必会》知识汇总二
  2. Py2neo:一种快速导入百万数据到Neo4j的方式
  3. 解决Win10更新后远程桌面提示CredSSP加密Oracle修正的问题
  4. 开源库libcli的安装与使用
  5. 基于U-Net网络的图像分割的MindStudio实践
  6. JDBC的一些基础认识,写的不是特别完善,希望大家看的时候别太介意嘿嘿嘿
  7. java中json字符串与实体类对象相互转换
  8. java后端整合极光消息推送
  9. 使用java代码调用rabbitmq接口进行新增编辑mq用户、虚拟机vhost、动态创建交换机exchange、队列queue以及设置权限,绑定vhost与exchange等操作
  10. [Leetcode]环形链表 II