题目链接:http://poj.openjudge.cn/practice/C15C/

题意:n 点 m 边 k 天。每条边在某一天会消失(仅仅那一天消失)。问每一天有多少对点可以相互到达。

解法:开始不会做,参考的YYN的题解:http://blog.csdn.net/u013368721/article/details/45725181

学习了这种CDQ加并查集的做法,可以说是非常的巧妙了。复杂度可以保证在:O(KlogklogK)的范围。

//CDQ + DSU
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int maxn = 100010;
const int maxe = 200010;
struct edge{
int u,v,next;
edge(){}
edge(int u,int v,int next):u(u),v(v),next(next){}
}E[maxn*2];
int n, m, k, head[maxn], edgecnt;
struct Node{
int u,v,cntu,cntv,rnku,rnkv;
Node(){}
Node(int u,int v,int cntu,int cntv,int rnku,int rnkv):u(u),v(v),cntu(cntu),cntv(cntv),rnku(rnku),rnkv(rnkv){}
};
Node S[maxe];
int cnt[maxn];
int p[maxn];
int rnk[maxn];
int top;
LL ans;
void init(){
top = 0;
ans = 0;
edgecnt=0;
memset(head,-1,sizeof(head));
}
void add(int id , int u, int v){
E[edgecnt] = edge (u, v, head[id]);
head[id] = edgecnt++;
}
int find_set(int x){
int o = x;
while(p[o] != o) o = p[o];
return o;
}
void union_set(int l, int r){
for(int t=l; t<=r; t++){
for(int i=head[t]; ~i; i=E[i].next){
int u = find_set(E[i].u);
int v = find_set(E[i].v);
if(u == v) continue;
S[top++] = Node(u, v, cnt[u], cnt[v], rnk[u], rnk[v]);
ans += (LL)cnt[u] * cnt[v];
if(rnk[u] <= rnk[v]){
rnk[v] = max(rnk[v], rnk[u]+1);
p[u] = v;
cnt[v] += cnt[u];
}
else{
p[v] = u;
cnt[u] += cnt[v];
}
}
}
}
void Back(int x)
{
while(top > x){
--top;
int u = S[top].u, v = S[top].v;
ans -= (LL)S[top].cntu*S[top].cntv;
p[u] = u;
p[v] = v;
cnt[u] = S[top].cntu;
cnt[v] = S[top].cntv;
rnk[u] = S[top].rnku;
rnk[v] = S[top].rnkv;
}
}
void CDQ(int l, int r)
{
if(l == r){
printf("%lld\n", ans);
return;
}
int mid=(l+r)>>1;
int rtop=top;
union_set(mid+1,r);
CDQ(l, mid);
Back(rtop);
union_set(l,mid);
CDQ(mid+1,r);
Back(rtop);
}
int main()
{
while(~scanf("%d %d %d", &n,&m,&k))
{
init();
for(int i=1; i<=n; i++){
p[i]=i;
cnt[i]=1;
rnk[i]=0;
}
int u, v, c;
for(int i=1; i<=m; i++){
scanf("%d %d %d", &u,&v,&c);
if(c > k){
u = find_set(u), v = find_set(v);
if(u == v) continue;
if(rnk[u]<=rnk[v]){
rnk[v]=max(rnk[v],rnk[u]+1);
p[u]=v;
cnt[v]+=cnt[u];
}
else{
p[v]=u;
cnt[u]+=cnt[v];
}
}
else{
add(c, u, v);
}
}
CDQ(1, k);
}
return 0;
}

【openjudge】C15C Rabbit's Festival CDQ分治+并查集的更多相关文章

  1. hdu_5354_Bipartite Graph(cdq分治+并查集判二分图)

    题目链接:hdu_5354_Bipartite Graph 题意: 给你一个由无向边连接的图,问对于每一个点来说,如果删除这个点,剩下的点能不能构成一个二分图. 题解: 如果每次排除一个点然后去DFS ...

  2. BZOJ 4025: 二分图 [线段树CDQ分治 并查集]

    4025: 二分图 题意:加入边,删除边,查询当前图是否为二分图 本来想练lct,然后发现了线段树分治的做法,感觉好厉害. lct做法的核心就是维护删除时间的最大生成树 首先口胡一个分块做法,和hno ...

  3. 【CF603E】Pastoral Oddities cdq分治+并查集

    [CF603E]Pastoral Oddities 题意:有n个点,依次加入m条边权为$l_i$的无向边,每次加入后询问:当前图是否存在一个生成子图,满足所有点的度数都是奇数.如果有,输出这个生成子图 ...

  4. 2018.10.01 bzoj3237: [Ahoi2013]连通图(cdq分治+并查集)

    传送门 cdq分治好题. 对于一条边,如果加上它刚好连通的话,那么删掉它会有两个大集合A,B.于是我们先将B中禁用的边连上,把A中禁用的边禁用,再递归处理A:然后把A中禁用的边连上,把B中禁用的边禁用 ...

  5. [HDU5354]Bipartite Graph(CDQ分治+并查集)

    经典动态二分图问题. 考虑solve(l,r)分治成l,mid和mid+1,r.先将区间[mid+1,r]中的点全部加入图中,若此时存在奇环则ans[l..mid]全部为0,否则递归到左边. 递归完左 ...

  6. 2018.09.30 bzoj4025: 二分图(线段树分治+并查集)

    传送门 线段树分治好题. 这道题实际上有很多不同的做法: cdq分治. lct. - 而我学习了dzyo的线段树分治+并查集写法. 所谓线段树分治就是先把操作分成lognlognlogn个连续不相交的 ...

  7. 2015多校第6场 HDU 5354 Bipartite Graph CDQ,并查集

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5354 题意:求删去每个点后图是否存在奇环(n,m<=1e5) 解法:很经典的套路,和这题一样:h ...

  8. 【CF576E】Painting Edges 线段树按时间分治+并查集

    [CF576E]Painting Edges 题意:给你一张n个点,m条边的无向图,每条边是k种颜色中的一种,满足所有颜色相同的边内部形成一个二分图.有q个询问,每次询问给出a,b代表将编号为a的边染 ...

  9. BZOJ_4025_二分图_线段树按时间分治+并查集

    BZOJ_4025_二分图_线段树按时间分治+并查集 Description 神犇有一个n个节点的图.因为神犇是神犇,所以在T时间内一些边会出现后消失.神犇要求出每一时间段内这个图是否是二分图.这么简 ...

随机推荐

  1. CSS3 边框 圆角 背景

    CSS3用于控制网页的样式布局. CSS3是最新的CSS标准.   关于transform: transform:rotate(10deg);//顺时针方向旋转10° 浏览器支持情况:低版本的IE浏览 ...

  2. BZOJ4832 抵制克苏恩(概率期望+动态规划)

    注意到A+B+C很小,容易想到设f[i][A][B][C]为第i次攻击后有A个血量为1.B个血量为2.C个血量为3的期望伤害,倒推暴力转移即可. #include<iostream> #i ...

  3. springboot2.0 如何异步操作,@Async失效,无法进入异步

    springboot异步操作可以使用@EnableAsync和@Async两个注解,本质就是多线程和动态代理. 一.配置一个线程池 @Configuration @EnableAsync//开启异步 ...

  4. 函数strcpy的实现

    strcpy函数的百科中给出了各种情况的详细说明,这里,仅给出一些注意事项: 1.strcpy的函数原型是: /* dest(destination)为目标字符串,src(source)为原字符串*/ ...

  5. BZOJ2761 不重复的数字 【treap】

    2761: [JLOI2011]不重复数字 Time Limit: 10 Sec  Memory Limit: 128 MB Submit: 5517  Solved: 2087 [Submit][S ...

  6. ContestHunter暑假欢乐赛 SRM 05

    T1 组合数,求一下乘法逆元就行了 没取模 没1LL* 爆零了 T2 让最大子段和最小就行,跑最大子段和的时候若超过S就弹出堆中最大的数,每次有负数加进来不断弹出最小的数相加重新加进堆直到为正数,因为 ...

  7. 将Visual Studio项目转换为Dot Net Core项目 csproj to xproj

    删除csproj文件. 将 package.config 重命名为 project.json . 转换文件,将xml转换为json格式. <?xml version="1.0" ...

  8. android源码了解dex加载流程

    源码版本:4.4.4_r1 http://www.cnblogs.com/lanrenxinxin/p/4712224.html http://wangzhixian.org/Others/DexCl ...

  9. mybatis 根据id批量删除的两种方法

    原文:https://blog.csdn.net/qq_40010745/article/details/81032218 mybatis 根据id批量删除的两种方法   第一种,直接传递给mappe ...

  10. 2017-7-18-每日博客-关于Linux下的鲜为人知的10条命令.doc

    这篇文章的目的是介绍一些少有人知的Linux命令,它们一定会高效地帮你管理你的桌面/服务器. 1. sudo !!命令 没有特定输入sudo命令而运行,将给出没有权限的错误.那么,你不需要重写整个命令 ...