CF :K 一个含n条边的带权无向连通图,q次查询,每次查询两点间的最短距离。
题意:给你一个含n条边的带权无向连通图,q次查询,每次查询两点间的最短距离。
思路:LCA+思维。
设a,b两点间的距离为f(a,b) 则f(a,b)=dis[a]+dis[b]-2*dis[lca(a,b)];
由于n条边,因此我们先任取一条边,设这条边为X,Y,权值为Z,设查询的点为x,y,则答案为
min(f(a,b),f(a,X)+f(b,X),f(a,Y)+f(b,Y),f(a,X)+f(b,Y)+Z,f(a,Y)+f(b,X)+Z);
#include<bits/stdc++.h>
#define lson (i<<1)
#define rson (i<<1|1) using namespace std;
typedef long long ll;
const int N =1e5+; struct node
{
int u,v,next;
int id,f;
ll w;
}edge[N*]; struct node1
{
int l,r;
ll w;
ll lz;
}tr[N<<]; int tot,head[N];
int n,q;
int anc[N<<][]; int dfn;
int dfns[N*];
int dep[N*];
int pos[N];
int inde[N];
int L[N];
int R[N];
int clo; int to[N];
int vis[N];
ll ww[N]; int uu,vv;
ll cost;
int huan;
int idd; void init()
{
tot=;
memset(head,-,sizeof(head));
memset(vis,,sizeof(vis));
memset(inde,-,sizeof(inde));
memset(pos,-,sizeof(pos));
clo=; huan=; idd=; dfn=; /// dfn竟然没清零 MMP
} void add(int u,int v,ll w,int id)
{
edge[++tot].u=u; edge[tot].v=v; edge[tot].id=id; edge[tot].w=w; edge[tot].f=;
edge[tot].next=head[u]; head[u]=tot;
} void dfs1(int u,int fa)
{
if(vis[u]){
uu=fa; vv=u; huan=; return ;
}
vis[u]=;
for(int i=head[u];i!=-;i=edge[i].next)
{
int v=edge[i].v;
if(v==fa) continue;
dfs1(v,u);
}
} void dfs2(int u,int deep) /// dfs序
{
//cout<<" u "<<u<<" deep "<<deep<<endl;
dfns[dfn]=u; dep[dfn]=deep; pos[u]=dfn++;
L[u]=++clo;
inde[u]=L[u]; /// 记录u在线段树中的位置
for(int i=head[u];i!=-;i=edge[i].next){
if(edge[i].f) continue; /// 如果是标记的边跳过
int v=edge[i].v;
if(pos[v]==-){
to[edge[i].id]=v; /// 表示这条边指向哪个点?
dfs2(v,deep+);
dfns[dfn]=u; dep[dfn++]=deep;
}
}
R[u]=clo;
} void init_RMQ(int n) /// dfn
{
for(int i=;i<=n;++i) anc[i][]=i;
for(int j=;(<<j)<=n;++j)
for(int i=;i+(<<j)-<=n;++i){
if(dep[anc[i][j-]]<dep[anc[i+(<<(j-))][j-]]) anc[i][j]=anc[i][j-];
else anc[i][j]=anc[i+(<<(j-))][j-];
}
} inline int RMQ(int L,int R)
{
int k=;
while(<<(k+)<=R-L+) ++k;
if(dep[anc[L][k]]<dep[anc[R-(<<k)+][k]]) return anc[L][k];
return anc[R-(<<k)+][k];
} inline int LCA(int u,int v)
{
if(pos[u]>pos[v]) return dfns[RMQ(pos[v],pos[u])];
return dfns[RMQ(pos[u],pos[v])];
} void push_up(int i)
{
tr[i].w=tr[lson].w+tr[rson].w;
} void push_down(int i)
{
if(tr[i].lz){ /// 查询只有点查询,所以不必更新区间点的sum
ll &lz=tr[i].lz;
tr[lson].lz+=lz; tr[rson].lz+=lz;
tr[lson].w+=lz; tr[rson].w+=lz;
lz=;
}
} void build(int i,int l,int r)
{
tr[i].l=l; tr[i].r=r; tr[i].w=; tr[i].lz=;
if(l==r) return ;
int mid=(l+r)>>;
build(lson,l,mid);
build(rson,mid+,r);
} void update(int i,int l,int r,ll w)
{
if(tr[i].l==l&&tr[i].r==r){
tr[i].lz+=w; tr[i].w+=w;
return ;
}
push_down(i);
int mid=(tr[i].l+tr[i].r)>>;
if(r<=mid) update(lson,l,r,w);
else if(l>mid ) update(rson,l,r,w);
else{
update(lson,l,mid,w);
update(rson,mid+,r,w);
}
push_up(i);
} ll query(int i,int aim)
{
if(tr[i].l==tr[i].r&&tr[i].l==aim){
return tr[i].w;
}
push_down(i);
int mid=(tr[i].l+tr[i].r)>>;
if(aim<=mid) return query(lson,aim);
else return query(rson,aim);
} ll getans(int u,int v)
{
int lca=LCA(u,v);
ll sum1,sum2,sum3;
sum1=query(,L[u]); sum2=query(,L[v]);
sum3=query(,L[lca]);
return sum1+sum2-sum3*;
} int main()
{
int T;
int u,v,op;
ll w;
scanf("%d",&T);
while(T--)
{
scanf("%d %d",&n,&q);
init();
for(int i=;i<=n;i++){
scanf("%d %d %lld",&u,&v,&w);
add(u,v,w,i);
add(v,u,w,i);
ww[i]=w;
} dfs1(,-);/// 第一遍dfs 先找到环中的任意一条边
for(int i=;i<=tot;i++){ /// 给边打上标记
if((edge[i].u==uu&&edge[i].v==vv)||(edge[i].u==vv&&edge[i].v==uu)){
edge[i].f=;
idd=edge[i].id;
cost=edge[i].w;
}
}
dfs2(,);
/*cout<<"dfn "<<dfn<<endl;
cout<<uu<<" *** "<<vv<<endl;
for(int i=1;i<=n;i++){
cout<<"l "<<L[i]<<" r "<<R[i]<<endl;
}
*/
init_RMQ(dfn); build(,,n); /// 以dfs的遍历出的 L,R 建树 那么接下来就是一个区间更新,单点查询的问题了
for(int i=;i<=n;i++){
if(i==idd) continue;
u=to[i];
update(,L[u],R[u],ww[i]);
}
/*
for(int i=1;i<=n;i++){
ll tmp=query(1,L[i]);
cout<<" dis "<<tmp<<endl;
}
*/ while(q--)
{ scanf("%d %d",&u,&v);
ll ans=getans(u,v);
ans=min(ans,getans(uu,u)+getans(vv,v)+cost); /// 经过标记的路的两个不同的方向。
ans=min(ans,getans(uu,v)+getans(vv,u)+cost);
printf("%lld\n",ans); } }
return ;
}
CF :K 一个含n条边的带权无向连通图,q次查询,每次查询两点间的最短距离。的更多相关文章
- 一个Notification 进度条插件(android,NJS实现,直接就可使用)
参考文章:http://ask.dcloud.net.cn/article/503 源码地址下载 如题,分享一个Notification 进度条插件(android,用js调用原生api实现,直接就可 ...
- SQL 拼接多个字段的值&一个字段多条记录的拼接 [轉]
例如student表: studentID studentName studentScore 01 Alice 90 02 Bill 95 03 Cindy 100 一.拼接多个字段的值 select ...
- 利用OpenCV和MFC对话框建设一个有滑动条控制的播放器--转
(一)问题的提出: OpenCV有一个很简单的播放视频文件并加载滑动条的程序,但是如何用MFC对话框来创建一个有滑动条控制的播放器呢,网络上四处搜索都没有代码可以参考,下的都是些骗子链接文件,很过分, ...
- 使用css3和伪元素制作的一个立体导航条
使用css3和伪元素制作的一个立体导航条供大家参考,代码如下: <!doctype html> <html lang="en"> <head> ...
- SQL 拼接多个字段的值&一个字段多条记录的拼接
如student表: studentID studentName studentScore 01 Alice 90 02 Bill 95 03 Cindy 100 一.拼接多个字段的值 select ...
- ZOJ 2588 Burning Bridges(求含重边的无向连通图的割边) - from lanshui_Yang
Burning Bridges Time Limit: 5 Seconds Memory Limit: 32768 KB Ferry Kingdom is a nice little country ...
- 【XSY1295】calc n个点n条边无向连通图计数 prufer序列
题目大意 求\(n\)个点\(n\)条边的无向连通图的个数 \(n\leq 5000\) 题解 显然是一个环上有很多外向树. 首先有一个东西:\(n\)个点选\(k\)个点作为树的根的生成森林个数为: ...
- [转]一个简单的Linux多线程例子 带你洞悉互斥量 信号量 条件变量编程
一个简单的Linux多线程例子 带你洞悉互斥量 信号量 条件变量编程 希望此文能给初学多线程编程的朋友带来帮助,也希望牛人多多指出错误. 另外感谢以下链接的作者给予,给我的学习带来了很大帮助 http ...
- K - Find them, Catch them POJ - 1703 (带权并查集)
题目链接: K - Find them, Catch them POJ - 1703 题目大意:警方决定捣毁两大犯罪团伙:龙帮和蛇帮,显然一个帮派至少有一人.该城有N个罪犯,编号从1至N(N<= ...
随机推荐
- SpringBoot16 MockMvc的使用、JsonPath的使用、请求参数问题、JsonView、分页查询参数、JsonProperty
1 MockMvc的使用 利用MockMvc可以快速实现MVC测试 坑01:利用MockMvc进行测试时应用上下文路径是不包含在请求路径中的 1.1 创建一个SpringBoot项目 项目脚手架 1. ...
- Marr的视觉计算理论
Marr的视觉计算理论立足于计算机科学,系统地概括了心理物理学.神经生理学.临床神经病理学等方面已取得的所有重要成果,是迄今为止最为系统的视觉理论.Marr 的视觉计算理论虽然在细节甚 ...
- Mac notes
1. Mac应用数据存放位置 ~/Library/Application Support/ 比如sublime text的应用数据~/Library/Application Support/Subli ...
- Linux cmus
一.简介 CMus 是一款类似于MOC, Herrie 或 mp3blaster 的基于终端的音乐播放器,支持 Ogg Vorbis, FLAC, MP3, WAV, Musepack, WavPac ...
- Linux 与 BSD
1)Linux 与 BSD 有什么不同? http://linux.cn/article-3186-1.html 2)BSD(Unix)家族 http://blog.csdn.net/cradmin/ ...
- 529A And Yet Another Bracket Sequence
传送门 题目大意 给定有一个长度为n n的括号序列,现在有两种操作: 在任意一个位置插入有一个左括号或右括号 将末尾的一个括号放到最前面 可以对这个序列进行若干次操作,问在使括号序列合法的前提下,长度 ...
- 手打的table
突然觉得,如果我不上传源码和写篇博客,对不起花在这个破网页2个小时的时间,完全手打,浏览器调效果. 源码如下: a.html: <!DOCTYPE html PUBLIC "-//W3 ...
- Codeforces 12D Ball(线段树)
N ladies attend the ball in the King's palace. Every lady can be described with three values: beauty ...
- Js杂谈-单体模式
单体模式的思想:保证一个特定类仅有一个实例,意味着第二次使用同一个类创建新对象的时候,应该得到与第一次所创建对象完全相同的对象. 下面举几个实现的例子 1.new操作符 这种思想在于当使用同一个构造函 ...
- C# winform使用cefsharp
注意事项写在开头: 一)cef要求.Net FrameWork框架最少为4.5.2,所以咱们在创建工程的时候注意 二)cef不支持anycpu平台 第一步: 新建工程 第二步 添加cef nuget ...