[UOJ61]怎样更有力气
这个题还是挺有意思的...
一个小结论是:在一个$n$点$m$边的图中,如果度数最小的点度数为$d$,那么$d^2=O(m)$,因为$d\leq\frac{2m}n$,所以$d^2\leq dn\leq2m$
把链按权值从小到大排序,对一条链$(u,v)$,设在它上面的限制数量为$k$,如果$k\lt\text{dis}(u,v)$,那么我们可以让这条链上的所有点连通,直接用并查集把链上的点暴力合并即可
否则我们想要在$O(k)$的时间内计算答案,这样这部分的总复杂度就是$O(p)$的
先把限制建成图,找到度数最小的那个点$x$,不与$x$相邻的那些点(设此集合再加上$x$为$X$)都可以和它合并,现在考虑那些与$x$相邻的点(设此集合为$Y$),只有两种可能的连边:$X\rightarrow Y$,$Y\rightarrow Y$
对于$X\rightarrow Y$,我们枚举$y\in Y$,如果$d_y\lt\left\lvert X\right\rvert$,那么它一定可以和$X$中某点连边,否则$O(d_y)$打标记再遍历所有$X$中节点即可,这部分复杂度是$O\left(\sum d_y\right)=O(k)$
对于$Y\rightarrow Y$,直接$O\left(d_x^2\right)$枚举即可,由开始的那个结论得这部分的复杂度也是$O(k)$
最后一个小问题是:要维护一个支持链并和两点并的并查集,这里维护两个并查集:链并的和实际集合的,在链并操作的同时更新实际集合的并查集即可
总复杂度$O(n+m\log m+q\alpha(n))$,跑得非常快
#include<stdio.h> #include<vector> #include<algorithm> using namespace std; typedef long long ll; const int inf=2147483647; int fa[300010],dep[300010],d[300010],f[300010],ot[300010],N,M; bool vis[300010]; ll ans; struct ch{ int x,y,w,i; }p[300010]; bool operator<(ch a,ch b){return a.w<b.w;} struct edge{ int x,y; edge(int x=0,int y=0):x(x),y(y){} }; vector<edge>e[300010]; vector<edge>::iterator it; vector<int>g[300010]; vector<int>::iterator i1,i2; struct dsu{ int fa[300010]; int get(int x){return x==fa[x]?x:(fa[x]=get(fa[x]));} }c,b; void merge(int x,int y,int w){ x=b.get(x); y=b.get(y); if(x!=y){ ans+=w; b.fa[x]=y; } } bool check(int x,int y,int k){ while(k--){ if(dep[x]<dep[y])swap(x,y); x=fa[x]; if(x==y)return 0; } return 1; } void get(int x,int y){ N=0; while(x!=y){ if(dep[x]<dep[y])swap(x,y); f[++N]=x; x=fa[x]; } f[++N]=x; } int main(){ int n,m,q,i,j,x,y,mn; scanf("%d%d%d",&n,&m,&q); for(i=2;i<=n;i++)scanf("%d",fa+i); for(i=1;i<=n;i++)dep[i]=dep[fa[i]]+1; for(i=1;i<=m;i++){ scanf("%d%d%d",&p[i].x,&p[i].y,&p[i].w); p[i].i=i; } while(q--){ scanf("%d%d%d",&i,&x,&y); e[i].push_back(edge(x,y)); } sort(p+1,p+m+1); for(i=1;i<=n;i++)c.fa[i]=b.fa[i]=i; for(i=1;i<=m;i++){ #define merge(x,y) merge(x,y,p[i].w) vector<edge>&v=e[p[i].i]; if(check(p[i].x,p[i].y,v.size())){ x=c.get(p[i].x); y=c.get(p[i].y); while(x!=y){ if(dep[x]<dep[y])swap(x,y); merge(x,fa[x]); c.fa[x]=fa[x]; x=c.get(x); } }else{ for(it=v.begin();it!=v.end();it++){ x=it->x; y=it->y; d[x]++; d[y]++; g[x].push_back(y); g[y].push_back(x); } get(p[i].x,p[i].y); x=0; mn=inf; for(j=1;j<=N;j++){ if(d[f[j]]<mn){ mn=d[f[j]]; x=f[j]; } } for(i1=g[x].begin();i1!=g[x].end();i1++)vis[*i1]=1; M=0; for(j=1;j<=N;j++){ if(!vis[f[j]])ot[++M]=f[j]; } for(j=1;j<=M;j++)merge(x,ot[j]); for(i1=g[x].begin();i1!=g[x].end();i1++)vis[*i1]=0; for(i1=g[x].begin();i1!=g[x].end();i1++){ y=*i1; for(i2=g[y].begin();i2!=g[y].end();i2++)vis[*i2]=1; for(i2=g[x].begin();i2!=g[x].end();i2++){ if(!vis[*i2])merge(y,*i2); } for(i2=g[y].begin();i2!=g[y].end();i2++)vis[*i2]=0; if((int)g[y].size()<M) merge(x,y); else{ for(i2=g[y].begin();i2!=g[y].end();i2++)vis[*i2]=1; for(j=1;j<=M;j++){ if(!vis[ot[j]])merge(ot[j],y); } for(i2=g[y].begin();i2!=g[y].end();i2++)vis[*i2]=0; } } for(it=v.begin();it!=v.end();it++){ x=it->x; y=it->y; d[x]=d[y]=0; g[x].clear(); g[y].clear(); } } } printf("%lld",ans); }
[UOJ61]怎样更有力气的更多相关文章
- UOJ#61. 【UR #5】怎样更有力气
大力水手问禅师:“大师,很多事情都需要用很大力气才能完成,而我在吃了菠菜之后力气很大,于是就导致我现在非常依赖菠菜.我很讨厌我的现状,有没有办法少吃点菠菜甚至不吃菠菜却仍很有力气?” 禅师浅笑,答:“ ...
- YYHS-怎样更有力气
题目描述 OI大师抖儿在夺得银牌之后,顺利保送pku.这一天,抖儿问长者:"我虽然已经保送了,但我的志向是为国家健康工作五十年.请问我应该怎样变得更有力气?" 长者回答:&quo ...
- 【NOIP2017练习】怎样更有力气(二分答案,线性扫描)
题意:OI大师抖儿在夺得银牌之后,顺利保送pku.这一天,抖儿问长者:“我虽然已经保送了,但我的志向是为国家健康工作五十年.请问我应该怎样变得更有力气?” 长者回答:“你啊,Too Young T ...
- 【UOJ#61】【UR #5】怎样更有力气(最小生成树)
[UOJ#61][UR #5]怎样更有力气(最小生成树) 题面 UOJ 题解 最最最暴力的想法是把所有边给处理出来然后跑\(MST\). 考虑边权的情况,显然离线考虑,把么一天按照\(w_i\)进行排 ...
- 「UR#5」怎样更有力气
「UR#5」怎样更有力气 解题思路 考虑没有限制的情况,一定是把操作离线下来,按照边权从小到达做.可以发现,如果没有限制,完全图是多余的,直接拿树边进行合并就可以了.我们要做这么一件事情,把每个点属于 ...
- UOJ61. 【UR #5】怎样更有力气
题目链接 Statement 给定一棵 \(n\) 点树 \(T\) 和 \(m\) 个操作 v u w : 在 \(T\) 中 \(u,v\) 的最短路上所有点里面选出若干对(可以不选,可以重复), ...
- 【UR #5】怎样更有力气
Problem Description 大力水手问禅师:"大师,很多事情都需要用很大力气才能完成,而我在吃了菠菜之后力气很大,于是就导致我现在非常依赖菠菜.我很讨厌我的现状,有没有办法少吃点 ...
- 校际联合Contest
每次开一个坑都像是重新被碾压的预感 最近的新闻,以前很喜欢乔任梁的<复活>...然后他就死了...感觉我再多愁善感一点的话...就要悲伤逆流成河了吧... Contest 09/24(乐滋 ...
- 如何编写高质量的 jQuery 代码?
想必大家对于jQuery这个最流行的javascript类库都不陌生,而且只要是前端开发人员肯定或多或少的使用或者接触过,在今天的这篇文章中,我们将介绍一些书写高质量jQuery代码的原则,我们不单单 ...
随机推荐
- wepy开发小程序 大坑....本地调试ok,小程序上传体验版 组件出现问题
如果你碰到的上述问题(本地调试ok,小程序上传体验版 各种莫名其妙的问题-卡死-组件属性失效-$apply()不起作用) 您需要关闭 微信开发者工具中: 1.微信开发者工具-->项目--> ...
- 1030 大数进制转换(51Nod + JAVA)
题目链接:https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1030 题目: 代码实现如下: import java.mat ...
- Aragorn's Story 树链剖分+线段树 && 树链剖分+树状数组
Aragorn's Story 来源:http://www.fjutacm.com/Problem.jsp?pid=2710来源:http://acm.hdu.edu.cn/showproblem.p ...
- NASA: A Closer View of the Moon(近距离观察月球)
Posted to Twitter by @Astro_Alex, European Space Agency astronaut Alexander Gerst, this image shows ...
- DNSLOG在渗透测试中的玩法儿
首先了解一下DNS是啥??? DNS(Domain Name System,域名系统),万维网上作为域名和IP地址相互映射的一个分布式数据库,能够使用户更方便的访问互联网,而不用去记住能够被机器直接读 ...
- #题目:有10 台被监控主机、一台监控机,在监控机上编写脚本,一旦某台被监控机器/ 分区适用率大于80%, 就发邮件报警放到crontab 里面, 每10 分钟检查一次
#题目:有10 台被监控主机.一台监控机,在监控机上编写脚本,一旦某台被监控机器/ 分区适用率大于80%, 就发邮件报警放到crontab 里面, 每10 分钟检查一次 #测试机器:虚拟机Linux ...
- ASP.NET Core 2.0 MVC 发布部署--------- linux安装.NET CORE SDK具体操作链接以及操作总细节
具体链接:https://www.microsoft.com/net/learn/get-started/linuxubuntu 如下图:
- ASP.NET Core 2.0 MVC 发布部署--------- SUSE 16 Linux Enterprise Server 12 SP2 X64 具体操作
.Net Core 部署到 SUSE 16 Linux Enterprise Server 12 SP2 64 位中的步骤 1.安装工具 1.apache 2..Net Core(dotnet-sdk ...
- BootStarp的form表单的基本写法
代码如下: <!DOCTYPE html> <html> <head> <title>BootStrap的基础入门</title> < ...
- 【摘要】JavaScript 的性能优化:加载和执行
1.浏览器遇到js代码会暂停页面的下载和渲染,谁晓得js代码会不会把html给强奸(改变)了: 2.延迟脚本加载:defer 属性 <html> <head> <titl ...