HDU6200 mustedge mustedge mustedge
建dfs树之后,在dfs树上加边其实就是让dfs树上一些边没有用了。(就这一点我想了很久才想到,真是zz啊)
//Serene
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<vector>
using namespace std;
const int maxn=1e5+10;
int T,n,m,Q; int aa,ff;char cc;
int read() {
aa=0;cc=getchar();ff=1;
while(cc<'0'||cc>'9') {
if(cc=='-') ff=-1;
cc=getchar();
}
while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
return aa*ff;
} struct Edge{
int u,v;
}; vector<Edge> G; int fir[maxn],nxt[2*maxn],to[2*maxn],e=0;
void add(int x,int y) {
to[++e]=y;nxt[e]=fir[x];fir[x]=e;
to[++e]=x;nxt[e]=fir[y];fir[y]=e;
} int f[maxn];
int find(int x) {return x==f[x]? x:f[x]=find(f[x]);} int fa[maxn],size[maxn],son[maxn],dep[maxn];
void dfs1(int pos) {
size[pos]=1;int y,z;
for(y=fir[pos];y;y=nxt[y]) {
if((z=to[y])==fa[pos]) continue;
fa[z]=pos;dep[z]=dep[pos]+1;
dfs1(z);
size[pos]+=size[z];
if(size[z]>size[son[pos]]) son[pos]=z;
}
} int id[maxn],top[maxn],cnt;
void dfs2(int pos,int tp) {
id[pos]=++cnt; top[pos]=tp;
if(!son[pos]) return;
dfs2(son[pos],tp);
int y,z;
for(y=fir[pos];y;y=nxt[y]) {
if((z=to[y])==fa[pos]||to[y]==son[pos]) continue;
dfs2(z,z);
}
} int sz[maxn]; int q(int l,int r) {
int rs=0;l--;
while(r) { rs+=sz[r]; r-=(r&-r); }
while(l) { rs-=sz[l]; l-=(l&-l); }
return rs;
} void chge(int l,int r){
int rr;
for(r=find(r);r>=l;r=f[r]) {
rr=r;
while(rr<=n){ sz[rr]--; rr+=(rr&-rr); }
f[r]=find(r-1);
}
} void get_lca(int x,int y,int p) {
int rs=0;
while(top[x]!=top[y]) {
if(dep[top[x]]<dep[top[y]]) swap(x,y);
if(p) rs+=q(id[top[x]],id[x]);
else chge(id[top[x]],id[x]);
x=fa[top[x]];
}
if(x!=y) {
if(dep[x]<dep[y]) swap(x,y);
if(p) rs+=q(id[y]+1,id[x]);
else chge(id[y]+1,id[x]);
}
if(p) printf("%d\n",rs);
} int main() {
T=read();
int x,y,z,xx,yy;
for(int qaq=1;qaq<=T;++qaq) {
n=read();m=read(); G.clear(); e=0; cnt=0;
memset(fir,0,sizeof(fir));
memset(son,0,sizeof(son));
memset(fa,0,sizeof(fa));
for(int i=1;i<=n;++i) f[i]=i;
for(int i=1;i<=m;++i) {
x=read();y=read();
xx=find(x);yy=find(y);
if(xx!=yy) add(x,y),f[xx]=yy;
else G.push_back(Edge{x,y});
}
Q=read(); dep[1]=1;
dfs1(1); dfs2(1,1);
for(int i=1;i<=n;++i) f[i]=i;
for(int i=1;i<=n;++i) sz[i]=(i&-i);
z=G.size();
for(int i=0;i<z;++i) get_lca(G[i].u,G[i].v,0);
printf("Case #%d:\n",qaq);
for(int i=1;i<=Q;++i) {
x=read();y=read();z=read();
get_lca(y,z,x-1);
}
}
return 0;
}
除此之外,也可以用树状数组维护每个点到根的距离,然后每次修改就是把子树的区间-1,这样就是区间修改单点查询了。
不过还是要用并查集维护每条边上方第一个没有清零的边(有用的边)。
所以说这道题的重点就是避免重复的修改浪费时间,用并查集维护上方第一个没有清零的边。
HDU6200 mustedge mustedge mustedge的更多相关文章
- hdu6200 mustedge mustedge mustedge (并查集+dfs序树状数组)
题意 给定一个n个点m条边无向图(n,m<=1e5) 支持两个操作 1.添加一条边 2.询问点u到点v的所有路径中必经边的条数 操作数<=1e5 分析 第一眼看起来像是要动态维护无向图的边 ...
- hdu 6200 mustedge mustedge(并查集+树状数组 或者 LCT 缩点)
hdu 6200 mustedge mustedge(并查集+树状数组 或者 LCT 缩点) 题意: 给一张无向连通图,有两种操作 1 u v 加一条边(u,v) 2 u v 计算u到v路径上桥的个数 ...
- 【一坨理论AC的题】Orz sxy大佬
1.UVA10891 Game of Sum 2.LA4254 Processor . 3.UVA10905 Children's Game 4.UVA11389 The Bus Driver Pro ...
随机推荐
- Java开发系列-时间转换
获取当前时间戳 // 获取当前的时间戳 long time = new Date().getTime(); 将字符串时间戳转成格式的时间字符串 Long timestrap = Long.parseL ...
- 关于java 线程的停止同时用 interrupt 和 join 的作用
/** * @FileName: ThreadTest.java * @Description: * @Author : xingchong * @CreateTime: Sep 22, 2018 1 ...
- 控制类名(className 属性)设置或返回class属性
控制类名(className 属性) className 属性设置或返回元素的class 属性. 语法: object.className = classname 作用: 1.获取元素的class 属 ...
- apache反向代理和监听多个端口设置
修改apache配置文件httpd.conf 一.监听多个端口 在Listen 80后添加监听端口,如 Listen 80 Listen 8080 Listen 8008 二.反向代理设置 1.取消一 ...
- centos6 php5.4 升級到php 5.6
因Centos6中的PHP版本有点底,需要升级PHP版本 [vagrant@localhost ~]$ php -v PHP 5.4.45 (cli) (built: Sep 30 2015 15:0 ...
- VC文件操作
VC文件操作 重命名文件: 注意: 该操作对文件夹一样有效! CFileFind Finder; CString sOldPath = _T("D:\\tt.txt"); CStr ...
- Redis安装过程:
- 从NoSQL到NewSQL数据库
- Exit- Linux必学的60个命令
1.作用 exit命令的作用是退出系统,它的使用权限是所有用户. 2.格式 exit 3.参数 exit命令没有参数,运行后退出系统进入登录界面.
- python configparser模块详解
此模块提供了一个实现基本配置语言的类 首先来看一个非常基本的配置文件,如下所示格式: [DEFAULT] ServerAliveInterval = 45 Compression = yes Comp ...