思路:

先把所有的加油站 push进按weight排序的优先队列里

对于每个不是加油站的点 找到到它的点的最短路以及它来源的加油站

如果x和y有边 且x和y加油站的来源不一样 则它可以连边

跑一边Kruskal

倍增查一下 搞定了

(注意图可能不连通)

//By SiriusRen
#include <queue>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define N 444444
int n,s,m,Station[N],rec[N],cnt,f[N],fa[N][35],maxx[N][35],T;
int q,xx,yy,zz,w[N],v[N],first[N],next[N],tot,vis[N],dis[N],deep[N];
struct Node{
int from,now,weight;
Node(){}
Node(int x,int y,int z){
from=x,now=y,weight=z;
}
}jy,node[N];
priority_queue<Node>pq;
bool operator < (Node a,Node b){
return a.weight>b.weight;
}
void add(int x,int y,int z){
w[tot]=z,v[tot]=y,next[tot]=first[x],first[x]=tot++;
}
void Dijkstra(){
while(!pq.empty()){
Node t=pq.top();pq.pop();
if(vis[t.now])continue;
vis[t.now]=1;
for(int i=first[t.now];~i;i=next[i])
if(dis[v[i]]>dis[t.now]+w[i]){
dis[v[i]]=dis[t.now]+w[i];
rec[v[i]]=t.from;
pq.push(Node(t.from,v[i],dis[v[i]]));
}
}
}
int W[N],V[N],NEXT[N],FIRST[N],TOT;
void add2(int X,int Y,int Z){
W[TOT]=Z,V[TOT]=Y,NEXT[TOT]=FIRST[X],FIRST[X]=TOT++;
}
int find(int x){return x==f[x]?x:f[x]=find(f[x]);}
void Kruskal(){
for(int i=1;i<=n;i++)f[i]=i;
sort(node+1,node+1+cnt);
for(int i=cnt;i;i--){
int fx=find(node[i].now),fy=find(node[i].from);
if(fx!=fy){
f[fx]=fy;
add2(node[i].now,node[i].from,node[i].weight);
add2(node[i].from,node[i].now,node[i].weight);
}
}
}
void dfs(int x,int father){
vis[x]=T;
for(int i=1;i<=29;i++){
fa[x][i]=fa[fa[x][i-1]][i-1];
maxx[x][i]=max(maxx[x][i-1],maxx[fa[x][i-1]][i-1]);
}
for(int i=FIRST[x];~i;i=NEXT[i])
if(V[i]!=father){
deep[V[i]]=deep[x]+1;
fa[V[i]][0]=x,maxx[V[i]][0]=W[i];
dfs(V[i],x);
}
}
int lca(int x,int y){
int ans=0;
if(deep[x]<deep[y])swap(x,y);
for(int i=29;~i;i--)
if(deep[x]-(1<<i)>=deep[y])
ans=max(ans,maxx[x][i]);x=fa[x][i];
if(x==y)return ans;
for(int i=29;~i;i--)
if(fa[x][i]!=fa[y][i]){
ans=max(ans,max(maxx[x][i],maxx[y][i]));
x=fa[x][i],y=fa[y][i];
}
return max(ans,max(maxx[x][0],maxx[y][0]));
}
int main(){
memset(FIRST,-1,sizeof(FIRST));
memset(first,-1,sizeof(first));
memset(dis,0x3f,sizeof(dis));
scanf("%d%d%d",&n,&s,&m);
for(int i=1;i<=s;i++){
scanf("%d",&xx);
dis[xx]=0,Station[xx]=1,rec[xx]=xx;
pq.push(Node(xx,xx,0));
}
for(int i=1;i<=m;i++){
scanf("%d%d%d",&xx,&yy,&zz);
add(xx,yy,zz),add(yy,xx,zz);
}
Dijkstra();
for(int i=1;i<=n;i++)
for(int j=first[i];~j;j=next[j])
if(rec[v[j]]!=rec[i]){
node[++cnt].from=rec[i],node[cnt].now=rec[v[j]];
node[cnt].weight=dis[i]+w[j]+dis[v[j]];
}
Kruskal(),memset(vis,0,sizeof(vis));
for(int i=1;i<=n;i++)
if(Station[i]&&!vis[i])
T++,dfs(i,-1);
scanf("%d",&q);
for(int i=1;i<=q;i++){
scanf("%d%d%d",&xx,&yy,&zz);
if(vis[xx]==vis[yy]&&lca(xx,yy)<=zz)puts("TAK");
else puts("NIE");
}
}

BZOJ 4144 Dijkstra+Kruskal+倍增LCA的更多相关文章

  1. BZOJ 3732 Network Kruskal+倍增LCA

    题目大意:给定一个n个点m条边的无向连通图.k次询问两点之间全部路径中最长边的最小值 NOIP2013 货车运输.差点儿就是原题...仅仅只是最小边最大改成了最大边最小.. . 首先看到最大值最小第一 ...

  2. BZOJ 3732 Network —— 最小生成树 + 倍增LCA

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3732 Description 给你N个点的无向图 (1 <= N <= 15, ...

  3. cf827D Best Edge Weight (kruskal+倍增lca+并查集)

    先用kruskal处理出一个最小生成树 对于非树边,倍增找出两端点间的最大边权-1就是答案 对于树边,如果它能被替代,就要有一条非树边,两端点在树上的路径覆盖了这条树边,而且边权不大于这条树边 这里可 ...

  4. 【BZOJ3732】 Network Kruskal+倍增lca

    Description 给你N个点的无向图 (1 <= N <= 15,000),记为:1…N. 图中有M条边 (1 <= M <= 30,000) ,第j条边的长度为: d_ ...

  5. cf609E Minimum Spanning Tree For Each Edge (kruskal+倍增Lca)

    先kruskal求出一个最小生成树,然后对于每条非树边(a,b),从树上找a到b路径上最大的边,来把它替换掉,就是包含这条边的最小生成树 #include<bits/stdc++.h> # ...

  6. BZOJ.4144.[AMPPZ2014]Petrol(Kruskal重构树)

    BZOJ 看别人代码的时候发现哪一步都很眼熟,突然想起来,就在四个月前我好像看过还给别人讲过?mmp=v= 果然不写写就是容易忘.写了好歹忘了的时候还能复习呢(虽然和看别人的好像也没多少差别?). 首 ...

  7. BFS+最小生成树+倍增+LCA【bzoj】4242 水壶

    [bzoj4242 水壶] Description JOI君所居住的IOI市以一年四季都十分炎热著称. IOI市是一个被分成纵H*横W块区域的长方形,每个区域都是建筑物.原野.墙壁之一.建筑物的区域有 ...

  8. BZOJ 2243: [SDOI2011]染色 树链剖分 倍增lca 线段树

    2243: [SDOI2011]染色 Time Limit: 20 Sec  Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeOnline/pr ...

  9. [BZOJ 4144] Petrol

    Link: BZOJ 4144 传送门 Solution: 一道不错的图论综合题 因为只询问关键点,因此重点是要求出关键点之间的最短路,以最短路建图 记$nst[i]$为离$i$最近的关键点:可以发现 ...

随机推荐

  1. 紫书 习题 11-17 UVa 1670 (图论构造)

    一开始要符合题目条件, 那么肯定没有任何一个点是孤立的, 也就是说没有点的度数是1 所以我就想让度数是1的叶子节点相互连起来.然后WA 然后看这哥们的博客 https://blog.csdn.net/ ...

  2. 在android中,编译的项目使用到第三方jar的导入方法 终极版!

    1,在android系统环境中编译自己的项目时,往往会用到第三方jar包.这些jar包在eclipse中加入编译,一路畅通,由于eclipse已经帮助你配置好了.可是当把这个项目复制到系统环境中编译时 ...

  3. 优秀Swift开源项目推荐

    工具类 SwiftyJSON:GitHub上最为开发者认可的JSON解析类 Safe.ijaimi:源码漏洞分析检测工具,一键完成 Dollar.swift:Swift版Lo-Dash(或unders ...

  4. bzoj1433: [ZJOI2009]假期的宿舍(最大二分图匹配)

    1433: [ZJOI2009]假期的宿舍 题目:传送门 题解: 这题有点水 跑个二分图匹配就完事了(注意在校生不是一定都互相认识) 代码: #include<cstdio> #inclu ...

  5. <Three.js>(第二节)添加长方体

    一.实验内容 上一节已经搭好了实验的框架.这一节我们将在屏幕上显示一些几何图形.如下图所示,我们将在屏幕上显示一个正方体. 二.实验步骤 1.创建场景 正像上一节所说,首先我们需要建一个场景,场景就是 ...

  6. codeforces 400 D Dima and Bacteria【并查集 Floyd】

    题意:给出n个点,分别属于k个集合,判断每个集合里面的点的距离都为0,为0的话输出yes,并输出任意两个集合之间的最短路 这道题目有两个地方不会处理, 先是n个点,分别属于k个集合,该怎么记录下来这里 ...

  7. Signal programming

    Signal programming is used in the same sense as dataflow programming, and is similar to event-driven ...

  8. 编译php并与nginx整合

    告诉 Nginx 如何处理 php 文件:          nginx>vim  conf/nginx.conf                     location ~ \.php${ ...

  9. NodeJS学习笔记 进阶 (11)Nodejs 进阶:调试日志打印:debug模块

    个人总结:读完这篇文章需要5分钟,讲解了debug模块的使用 摘选自网络 前言 在node程序开发中时,经常需要打印调试日志.用的比较多的是debug模块,比如express框架中就用到了.下文简单举 ...

  10. SQL替换制表、回车、换行符和首尾空格

    SQL替换制表.回车.换行符和首尾空格 最近在批量修复数据的时候,需要利用excel导入大量数据.客户提供的数据是没有规范的,大部分数据行都有制表符.回车符.换货符,以及我需要将数据进行首位去重. 目 ...