hdu 5458 Stability(树链剖分+并查集)
Stability
Time Limit: 3000/2000 MS (Java/Others) Memory Limit: 65535/102400 K (Java/Others)
Total Submission(s): 1347 Accepted Submission(s): 319
You need to maintain the graph G, support the deletions of edges (though we guarantee the graph would always be connected), and answer the query of stability for two given nodes.
For each test case, the first line contains three integers n, m and q, where 1≤n≤3×104,1≤m≤105 and 1≤q≤105. The nodes in graph G are labelled from 1to n.
Each of the following m lines contains two integers u and v describing an undirected edge between node u and node v.
Following q lines - each line describes an operation or a query in the formats:
⋅ 1 a b: delete one edge between a and b. We guarantee the existence of such edge.
⋅ 2 a b: query the stability between a and b.
Then for each query, print one line containing the stability between corresponding pair of nodes.
10 12 14
1 2
1 3
2 4
2 5
3 6
4 7
4 8
5 8
6 10
7 9
8 9
8 10
2 7 9
2 7 10
2 10 6
2 10 5
1 10 6
2 10 1
2 10 6
2 3 10
1 8 5
2 5 10
2 4 5
1 7 9
2 7 9
2 10 5
0
0
0
0
2
4
3
3
2
3
4
/*
hdu 5458 Stability(树链剖分+并查集) problem:
给你一个无向图(可能有重边or环). 1.删除a,b之间的边 2.查询a,b的必要边(即删除后a b无法连通) solve:
最开始想的是建图的时候一直维持一棵树. 如果u,v上面出现环,那么u->v整个链上都可以置为0.因为它们任意两点之间都不可能有必要边
但是后面操作中会删除边,所以不知道树的形状,会导致后面的查询出现问题. 后来考虑倒着操作,先弄出最后操作完的图.本来还担心最后会被切成多个不相连图, 但是
题目:we guarantee the graph would always be connected 保证了操作完后必然是 树或者有环图.
如果是有环图的话可以用过上面的思路转换成树的,最后就成了树链上的操作,所以树链剖分就能做 将所有边记录下来,然后将1操作删除的边除去. 如果最后是有环图(并查集判断)的话,将重复的边记录下,然后建树.
而重复的边会导致 u->v链上面两两没有必要边,于是将置为0. 得出了最后这个树,接着就是倒着操作了
1操作:在u->v上加边 ----> 将u->v整个链上都可以置为0
2操作:查询u->v上的必要边 hhh-2016-08-26 11:06:45
*/
#pragma comment(linker,"/STACK:124000000,124000000")
#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <vector>
#include <math.h>
#include <queue>
#include <map>
#include <set>
#define lson i<<1
#define rson i<<1|1
#define ll long long
#define clr(a,b) memset(a,b,sizeof(a))
#define scanfi(a) scanf("%d",&a)
#define scanfl(a) scanf("%I64d",&a)
#define key_val ch[ch[root][1]][0]
#define inf 0x3f3f3f3f
using namespace std;
const int maxn = 40010;
const int maxm = 2e5 + 1000;
int head[maxn],tot,pos,son[maxn];
int top[maxn],fp[maxn],fa[maxn],dep[maxn],num[maxn],p[maxn];
int par[maxn];
int n,m,q;
struct Edge
{
int to,next;
} edge[maxm << 1];
int fin_par(int x)
{
if(par[x] == -1) return x;
return par[x] = fin_par(par[x]);
}
void ini()
{
clr(par,-1);
tot = 0,pos = 1;
clr(head,-1),clr(son,-1);
} void add_edge(int u,int v)
{
edge[tot].to = v,edge[tot].next = head[u],head[u] = tot++;
} void dfs1(int u,int pre,int d)
{
// cout << u << " " <<pre <<" " <<d <<endl;
dep[u] = d;
fa[u] = pre,num[u] = 1;
for(int i = head[u]; ~i; i = edge[i].next)
{
int v = edge[i].to;
if(v != pre)
{
dfs1(v,u,d+1);
num[u] += num[v];
if(son[u] == -1 || num[v] > num[son[u]])
son[u] = v;
}
}
} void getpos(int u,int sp)
{
top[u] = sp;
p[u] = pos++;
fp[p[u]] = u;
if(son[u] == -1)return ;
getpos(son[u],sp);
for(int i = head[u]; ~i ; i = edge[i].next)
{
int v = edge[i].to;
if(v != son[u] && v != fa[u])
getpos(v,v);
}
} struct node
{
int same;
int val;
int l,r,mid;
} tree[maxn << 2]; void push_up(int i)
{
tree[i].val = tree[lson].val + tree[rson].val;
} void build(int i,int l,int r)
{
tree[i].same = -1;
tree[i].l = l,tree[i].r = r;
tree[i].mid=(l+r) >>1; if(l == r)
{
if(fp[l] == 1)
tree[i].val = 0;
else
tree[i].val = 1;
// cout << fp[l]<<":" << tree[i].val <<endl;
return;
}
build(lson,l,tree[i].mid);
build(rson,tree[i].mid+1,r);
push_up(i);
} void push_down(int i)
{
if(tree[i].same != -1)
{
tree[lson].same = tree[i].same;
tree[rson].same = tree[i].same;
tree[lson].val = tree[rson].val = 0;
tree[i].same = -1;
}
} void update_area(int i,int l,int r)
{
if(tree[i].l >= l && tree[i].r <= r)
{
tree[i].val= 0;
tree[i].same= 0;
return ;
}
push_down(i);
if(l <= tree[i].mid)
update_area(lson,l,r);
if(r > tree[i].mid)
update_area(rson,l,r);
push_up(i);
return ;
} int query(int i,int l,int r)
{
if(tree[i].l >= l && tree[i].r <= r)
return tree[i].val;
int tcnt = 0;
push_down(i);
if(l <= tree[i].mid)
tcnt += query(lson,l,r);
if(r > tree[i].mid)
tcnt += query(rson,l,r);
push_up(i);
return tcnt;
} void make_update(int u,int v)
{
int f1 = top[u],f2 = top[v];
while(f1 != f2)
{
if(dep[f1] < dep[f2])swap(f1,f2),swap(u,v);
update_area(1,p[f1],p[u]);
u = fa[f1] , f1 =top[u];
}
if(u == v)
return ;
if(dep[u] > dep[v]) swap(u,v);
update_area(1,p[son[u]],p[v]);
} int make_query(int u,int v)
{
int ans = 0;
int f1= top[u],f2 = top[v];
while(f1 != f2)
{
if(dep[f1] < dep[f2])
{
swap(f1,f2),swap(u,v);
}
ans += query(1,p[f1],p[u]);
// cout << p[f1] <<" " <<p[u] <<" "<<ans << endl;
u = fa[f1] , f1 = top[u];
}
if(u == v)
return ans;
if(dep[u] > dep[v]) swap(u,v);
ans += query(1,p[son[u]],p[v]);
// cout << p[u]+1 <<" " <<p[v] <<" "<<ans << endl;
return ans ;
} int l[maxm],r[maxm],op[maxm];
int ans[maxm];
struct Point
{
int l,r;
Point() {}
Point(int x,int y):l(x),r(y) {}
bool operator <(const Point &a)const
{
if(l != a.l)
return l < a.l;
else
return r < a.r;
}
};
multiset<Point> vec;
multiset<Point> another;
multiset<Point>::iterator it;
int main()
{
// freopen("in.txt","r",stdin);
int T,u,v,cas = 1;
scanfi(T);
while(T--)
{
ini();
vec.clear(),another.clear();
scanfi(n),scanfi(m),scanfi(q);
for(int i = 1; i <= m; i++)
{
scanfi(u),scanfi(v);
if(u > v) swap(u,v);
vec.insert(Point(u,v));
}
for(int i = 1; i <= q; i++)
{
scanf("%d%d%d",&op[i],&l[i],&r[i]);
if(op[i] == 1)
{
if(l[i] > r[i]) swap(l[i],r[i]);
vec.erase(vec.lower_bound(Point(l[i],r[i])));
}
}
// cout << vec.size() <<endl;
for( it = vec.begin(); it != vec.end(); it++)
{
Point t = *it;
u = t.l,v = t.r;
int tu = fin_par(u),tv = fin_par(v);
// cout << u <<" " << v << " " << tu << " " <<tv <<endl;
if(tu == tv)
{
another.insert(Point(u,v));
continue;
}
par[tu] = tv;
add_edge(u,v);
add_edge(v,u);
}
// cout << another.size() <<endl;
dfs1(1,0,0);
getpos(1,1);
build(1,1,pos-1);
printf("Case #%d:\n",cas++);
for( it = another.begin(); it != another.end(); it++)
{
Point t = *it;
u = t.l,v = t.r;
make_update(u,v);
}
int ob = 0;
for(int i = q; i > 0; i--)
{
u = l[i],v = r[i];
// cout << op[i]<<" "<< u << " " << v <<endl; if(op[i] == 2)
{
ans[ob++] = make_query(u,v);
}
else
{
make_update(u,v);
}
}
for(int i = ob-1;i >=0;i--)
{
printf("%d\n",ans[i]);
}
}
return 0;
}
hdu 5458 Stability(树链剖分+并查集)的更多相关文章
- HDU 5458 Stability (树链剖分+并查集+set)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5458 给你n个点,m条边,q个操作,操作1是删边,操作2是问u到v之间的割边有多少条. 这题要倒着做才 ...
- bzoj3694: 最短路(树链剖分/并查集)
bzoj1576的帮我们跑好最短路版本23333(双倍经验!嘿嘿嘿 这题可以用树链剖分或并查集写.树链剖分非常显然,并查集的写法比较妙,涨了个姿势,原来并查集的路径压缩还能这么用... 首先对于不在最 ...
- [BZOJ2238]Mst 最小生成树+树链剖分/并查集
链接 题解 先构建出最小生成树,如果删的是非树边,直接输出答案 否则问题转化为,把该边删掉后剩下两个联通块,两个端点分别在两个块内的最小边权,LCT可以维护 不妨换一种思考方向:考虑一条非树边可以代替 ...
- HDU 5044 (树链剖分+树状数组+点/边改查)
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5044 题目大意:修改链上点,修改链上的边.查询所有点,查询所有边. 解题思路: 2014上海网赛的变 ...
- HDU 3966(树链剖分+点修改+点查询)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3966 题目大意:营地的分布成树型.每个营地都有一些人,每次修改修改一条链上的所有营地的人数,每次查询单 ...
- HDU 5044 Tree --树链剖分
题意:给一棵树,两种操作: ADD1: 给u-v路径上所有点加上值k, ADD2:给u-v路径上所有边加上k,初始值都为0,问最后每个点和每条边的值,输出. 解法:树链剖分可做,剖出来如果直接用线段树 ...
- HDU - 3966-Aragorn' Story(树链剖分+线段树)
链接:https://vjudge.net/problem/HDU-3966 题意: Our protagonist is the handsome human prince Aragorn come ...
- HDU 3966 RE 树链剖分 线段树 Aragorn's Story
题意: 给出一棵树,每个顶点上有一个权值. 操作:选择一条路径,并将路径上所有的点的权值同时加或减某个数. 查询:某个点的当前权值 分析: 树链剖分完毕后,就是简单的线段树区间更新. 提交的时候注意要 ...
- HDU 5242 利用树链剖分思想进行贪心
题目大意: 在给定带权值节点的树上从1开始不回头走到某个底端点后得到所有经过的点的权值后,这些点权值修改为0,到达底部后重新回到1,继续走,问走k次,最多能得到多少权值之和 这其实就是相当于每一次都走 ...
随机推荐
- C程序第一次作业
1-1 计算两数的和与差 1 设计思路 (1)主要描述题目算法 第一步:利用指针psum接收sum的地址,指针pdiff接收diff的地址,因此 * psum为sum, * pdiff为diff. 第 ...
- 如何减小ios安装包大小
以前的老文章了,搬到cnblog 更小的安装包意味着更快的下载安装速度,也往往意味着更快的加载运行速度,是优化ios应用的一个重要方面,本文主要参考<减小iOS应用程序的大小>,在实际测试 ...
- C++数据结构中的基本算法排序
冒泡排序 基本思想:两两比较待排序的数,发现反序时交换,直到没有反序为止. public static void BubbleSort(int[] R) { for (int i = 0; i < ...
- 算法第四版学习笔记之快速排序 QuickSort
软件:DrJava 参考书:算法(第四版) 章节:2.3快速排序(以下截图是算法配套视频所讲内容截图) 1:快速排序 2:
- Tornado 网站demo 一
web服务器的工作过程 创建 listen socket, 在指定的监听端口, 等待客户端请求的到来 listen socket 接受客户端的请求, 得到 client socket, 接下来通过 c ...
- 火车头采集器对接织梦cms图集发布时, 采集网上图片超时的解决方法
背景介绍: 火车头采集器对接织梦cms图片集发布时, 对于多张(超过30张)大图片时, 经常会出现图集发布超时的情况. 问题分析: 因为php对于资源的处理有默认的超时时间30秒, 而我尝试了好多方 ...
- 调用WCF时,调用已超过传入消息(65536)的最大消息大小配额。若要增加配额,请使用相应绑定。
解决方案: 其实只要在客户端配置文件中加上如下紫色粗体属性( maxReceivedMessageSize): <?xml version="1.0" encoding=&q ...
- Pandas速查手册中文版
本文翻译自文章: Pandas Cheat Sheet - Python for Data Science ,同时添加了部分注解. 对于数据科学家,无论是数据分析还是数据挖掘来说,Pandas是一个非 ...
- float和position
float float是欺骗父元素,让其父元素误以为其高度塌陷了,但float元素本身仍处于文档流中,文字会环绕着float元素,不会被遮蔽. absolute 但absolute其实已经不能算是欺骗 ...
- Python基础数据类型之int、bool、str
数据类型:int bool str list 元祖 dict 集合 int:整数型,用于各种数学运算. bool:只有两种,True和False,用户判断. str:存储少量数据,进行操作 ...