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.代码 #include<stdio.h> int main() { int a,b; float c; scanf("%d %d",& ...
- 201621123043《java程序设计》第4周学习总结
1. 本周学习总结 1.1 写出你认为本周学习中比较重要的知识点关键词 关键字:继承.覆盖.多态 1.2 尝试使用思维导图将这些关键词组织起来.注:思维导图一般不需要出现过多的字. 1.3 可选:使用 ...
- 《高级软件测试》Linux平台Jira的安装与配置
现在大部分的程序开发都是在linux下进行的,jira更多的时候是安装在linux上,那么,如何在linux下安装配置jira呢?本文将以Ubuntu 17.10和jira7.5.2为例,对linux ...
- nyoj 仿射密码
仿射密码 时间限制:1000 ms | 内存限制:65535 KB 难度:1 描述 仿射密码是替换密码的另一个特例,可以看做是移位密码和乘数密码的结合.其加密变换如下: E(m)=(k1*m+k2) ...
- mysql数据库基本操作
下载地址 http://www.mysql.com/downloads/mysql/ 端口号:3306 用户名:root 密码:自定义 连接到MySQL服务器 >mysql -uroot -pr ...
- C# HttpClient设置cookies的两种办法 (转发)
一般有两种办法 第一种handler.UseCookies=true(默认为true),默认的会自己带上cookies,例如 var handler = new HttpClientHandler() ...
- python入门(6)输入和输出
python入门(6)输入和输出 输出 >>> print 'hello, world' >>> print 'The quick brown fox', 'jum ...
- ssm框架找不到mysql驱动类WARN DriverManagerDataSource:107 - Could not load driverClass com.mysql.jdbc.Driver
找了很久错误,检查了配置文件,和spring配置数据源,都没有发现问题,最后上网查询了下,发现是由于配置文件后面有空格. 去除掉配置文件后面的空格就可以正常运行了.
- [洛谷P1197/BZOJ1015][JSOI2008]星球大战Starwar - 并查集,离线,联通块
Description 很久以前,在一个遥远的星系,一个黑暗的帝国靠着它的超级武器统治者整个星系.某一天,凭着一个偶然的机遇,一支反抗军摧毁了帝国的超级武器,并攻下了星系中几乎所有的星球.这些星球通过 ...
- JavaScript sort() 方法
定义和用法 sort() 方法用于对数组的元素进行排序. 语法 arrayObject.sort(sortby) 参数 描述 sortby 可选.规定排序顺序.必须是函数. 返回值 对数组的引用.请注 ...