在下觉得这是一道很鬼畜的神题,因为在下第一眼觉得要用整体二分做。

虽然在下已经知道它是Kruskal+lca了,还是仍不住想试着用整体二分,然后写了一个自认为十分好看的优秀代码,十分优秀的T了。。

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<queue>
#include<vector>
typedef long long LL;
using namespace std;
const int maxn=15000+299;
const int maxm=30000*2+299;
const int maxk=20000+299;
int upp=0,n,m,k,ecnt,fir[maxn],nxt[maxm],to[maxm],val[maxm],vis[maxn];
struct node {int x,y,id,ans;
}p[maxk],tp[maxk];
void add(int u,int v,int w) {nxt[++ecnt]=fir[u]; fir[u]=ecnt; to[ecnt]=v; val[ecnt]=w;nxt[++ecnt]=fir[v]; fir[v]=ecnt; to[ecnt]=u; val[ecnt]=w;
}
bool cmp(node x,node y) {return x.id<y.id;
}
queue<int>que;
void bfs(int s,int lim) {que.push(s); vis[s]=s;while(!que.empty()) {int x=que.front();que.pop();for(int i=fir[x];i;i=nxt[i]) if(val[i]<=lim&&vis[to[i]]!=s) {vis[to[i]]=s;que.push(to[i]); }}
}
void solve(int l,int r,int ql,int qr) {if(ql>qr||l>r) return; int mid=(ql+qr)>>1;memset(vis,0,sizeof(vis));for(int i=1;i<=n;i++) if(!vis[i]) bfs(i,mid);int lt=l,rt=r;for(int i=l;i<=r;i++) {if(vis[p[i].x]==vis[p[i].y]) {p[i].ans=mid; tp[lt++]=p[i];}else tp[rt--]=p[i];}for(int i=l;i<=r;i++) p[i]=tp[i];solve(l,lt-1,ql,mid-1); solve(lt,r,mid+1,qr);
}
int main()
{//freopen(".in","r",stdin);//freopen(".out","w",stdout);scanf("%d%d%d",&n,&m,&k);for(int i=1;i<=m;i++) {int x,y,z;scanf("%d%d%d",&x,&y,&z);add(x,y,z);upp=max(upp,z);}for(int i=1;i<=k;i++) {scanf("%d%d",&p[i].x,&p[i].y);p[i].id=i; p[i].ans=-1;}solve(1,k,1,upp);sort(p+1,p+k+1,cmp);for(int i=1;i<=k;i++) {printf("%d\n",p[i].ans);}return 0;
}

View Code

然后正解,没什么想说的,反正我十分难受。

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<queue>
#include<vector>
typedef long long LL;
using namespace std;
const int maxn=15000+299;
const int maxm=30000*2+299;
const int maxk=20000+299;
int upp=0,tot,n,m,k,ecnt,fir[maxn],nxt[maxm],to[maxm],val[maxm],vis[maxn],fa[maxn];
int f[maxn][32],st[maxn][32],R[maxn];
struct edge{int u,v,w;friend bool operator <(const edge&A,const edge&B) {return A.w<B.w;}
}e[maxm];
void add(int u,int v,int w) {nxt[++ecnt]=fir[u]; fir[u]=ecnt; to[ecnt]=v; val[ecnt]=w;nxt[++ecnt]=fir[v]; fir[v]=ecnt; to[ecnt]=u; val[ecnt]=w;
}
void init() {scanf("%d%d%d",&n,&m,&k);for(int i=1;i<=m;i++) scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].w);
}
int find(int x) {return x==fa[x]?x:fa[x]=find(fa[x]);}
void kruskal() {sort(e+1,e+m+1);for(int i=1;i<=n;i++) fa[i]=i;for(int i=1;i<=m;i++) {int u=e[i].u,v=e[i].v;int fu=find(u),fv=find(v);if(fu!=fv) {add(u,v,e[i].w);tot++;if(tot==n-1) break;fa[fu]=fv;}}
}
void dfs(int x,int ff) {f[x][0]=ff; R[x]=R[ff]+1;for(int i=fir[x];i;i=nxt[i]) if(to[i]!=ff){st[to[i]][0]=val[i];dfs(to[i],x);}
}
void make_st() {for(int i=1;i<=30;i++)for(int j=1;j<=n;j++) {f[j][i]=f[f[j][i-1]][i-1];st[j][i]=max(st[j][i-1],st[f[j][i-1]][i-1]);    }
}
int lca(int x,int y) {int res=0;if(R[x]<R[y]) swap(x,y);for(int i=30;i>=0;i--) {if(R[f[x][i]]>=R[y]) { res=max(res,st[x][i]);x=f[x][i]; }}if(x==y) return res;for(int i=30;i>=0;i--) {if(f[x][i]!=f[y][i]) {res=max(res,st[x][i]);res=max(res,st[y][i]);x=f[x][i]; y=f[y][i];}}res=max(res,st[x][0]);res=max(res,st[y][0]);return res;
}
void work() {for(int i=1;i<=k;i++) {int x,y;scanf("%d %d",&x,&y);printf("%d\n",lca(x,y));}
}
int main()
{init();kruskal();dfs(1,0);make_st();work();return 0;
}

View Code

转载于:https://www.cnblogs.com/Achenchen/p/7554475.html

BZOJ 3732 Network相关推荐

  1. 倍增LCA(bzoj 3732: Network)

    3732: Network Time Limit: 10 Sec  Memory Limit: 128 MB Submit: 1836  Solved: 868 [Submit][Status][Di ...

  2. 3732: Network

    3732: Network Time Limit: 10 Sec  Memory Limit: 128 MB Submit: 395  Solved: 179 [Submit][Status] Des ...

  3. php 正则匹配乱码,php正则匹配utf-8编码的中文汉字

    在javascript中,要判断字符串是中文是很简单的.比如: var str = "php编程"; if (/^[\u4e00-\u9fa5]+$/.test(str)) { a ...

  4. kruskal 重构树(讲解 + 例题)

    kruskal重构树 如何建树 模仿kruskalkruskalkruskal,先将所有边排序. 依次遍历每一条边,如果这条边的两个节点(u,vu, vu,v)不在同一个连通块里面, 则新建一个nod ...

  5. 一句话题解(20170801~20170125)

    8.1 bzoj 4720 noip2016 换教室 floyd预处理+期望(薛定谔的猫) bzoj 4318 OSU! 三次函数期望值 从一次.二次推得 8.2 bzoj 1076 状压+期望DP ...

  6. jiedai算法模板合集(正在肝2021.8.15)

    文章目录 基础模板 常用板子 数学题常用板子 输出挂 fread快读 高精度 分数类 打表压缩 基数排序 杂项 数据结构 树状数组 一维树状数组 二维树状数组 线段树 主席树 线段树合并/裂开 吉司机 ...

  7. [BZOJ 1834] [ZJOI2010]network 网络扩容

    1834: [ZJOI2010]network 网络扩容 Time Limit: 3 SecMemory Limit: 64 MB Description 给定一张有向图,每条边都有一个容量C和一个扩 ...

  8. BZOJ 1146: [CTSC2008]网络管理Network( 树链剖分 + 树状数组套主席树 )

    树链剖分完就成了一道主席树裸题了, 每次树链剖分找出相应区间然后用BIT+(可持久化)权值线段树就可以完成计数. 但是空间问题很严重....在修改时不必要的就不要新建, 直接修改原来的..详见代码. ...

  9. 【BZOJ】1834: [ZJOI2010]network 网络扩容(最大流+费用流)

    http://www.lydsy.com/JudgeOnline/problem.php?id=1834 我又思考人生了T_T,nd的数组开小了,一直wa,调了一个小时才发现啊!!!!!我一直以为我的 ...

最新文章

  1. php 远程下载图片到本地
  2. 南京大学计算机学院袁健,袁健(南京大学大气科学学院教授)_百度百科
  3. js async await 终极异步解决方案
  4. dnslog 在 sql注入中的应用
  5. 设计行业的新宠——云渲染
  6. android gif 处理,gifflen 调用以及错误处理
  7. L323 英语有必要学语法吗
  8. ios 视图切换翻页效果
  9. iOS开发之控制器之间传值
  10. 兄弟姐妹们,祝大家圣诞节快乐!
  11. Z国的货币系统包含面值1元、4元、16元、64元共计4种硬币,以及面值1024元的纸币。现在小Y使用1024元的纸币购买了一件价值为N的商品,请问最少他会收到多少硬币?
  12. kafka自带的zk启动_kafka单机安装和启动
  13. 实现你人生中的第一个jQuery插件
  14. 基于Xilinx Kintex-7 FPGA K7 XC7K325T PCIeX8 四路光纤卡226
  15. SSE(Server-sent Events)实现Web消息推送(SpringBoot)
  16. Java代理模式分析
  17. 小学计算机输入法主题教研设计,《拼音输入法》教学设计.doc
  18. 推荐多样性重排算法之MMR
  19. spring如何排除bean的注入
  20. 矩阵分析学习(补充)

热门文章

  1. Visual studio 利用Nuget 控制台安装已经下载好的插件
  2. spring实战六之使用基于java配置的Spring
  3. Linux多线程实践(8) --Posix条件变量解决生产者消费者问题
  4. 扩展ToolBarManager、ListView和Grid控件以实现气球式的ToolTip
  5. C#分隔字符串时遭遇空值
  6. netperf -R用法
  7. linux进程--虚拟地址空间布局(十一)
  8. linux系统读取第二个盘的数据,磁盘及文件系统管理—第二篇
  9. CGRect CGFloat 不能使用
  10. 【跃迁之路】【678天】程序员高效学习方法论探索系列(实验阶段435-2018.12.23)...