发现自己Tarjan的板子有错误.发现可以用Map直接删去边,Get.

听说std是双连通、LCA、并查集、离线思想、用BIT维护dfs序和并查集维护LCA的动态缩点的好题

 #include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <map>
#include <set>
#include <stack>
#define mp make_pair
#define pa pair<int,int>
#define pb push_back
#define fi first
#define se second
using namespace std;
inline void Get_Int(int &x)
{
x=; char ch=getchar(); int f=;
while (ch<'' || ch>'') {if (ch=='-') f=-; ch=getchar();}
while (ch>='' && ch<='') {x=x*+ch-''; ch=getchar();} x*=f;
}
inline void Put_Int(int x)
{
char ch[]; int top=;
if (x==) ch[++top]='';
while (x) ch[++top]=x%+'',x/=;
while (top) putchar(ch[top--]); putchar('\n');
}
//===================================================
const int Maxm=;
const int Maxn=;
const int Maxop=;
struct EDGE{int to,next;}edge[Maxm];
struct OP{int type,u,v;}Op[Maxop];
int head[Maxn],siz[Maxn],father[Maxn],top[Maxn],dep[Maxn],num[Maxn],sum[Maxn<<],clr[Maxn<<];
int Belong[Maxn],Low[Maxn],Dfn[Maxn],Ans[Maxn];
int Stack[Maxn];
int stamp,Stamp,cnt,scc,apex,Q,n,m,u,v;
bool vis[Maxn];
map<pa,bool> Edge;
vector<pa> V;
set <pa> S;
inline void Add(int u,int v)
{edge[cnt].to=v;edge[cnt].next=head[u];head[u]=cnt++;}
inline int Max(int x,int y) {return x>y?x:y;}
inline int Min(int x,int y) {return x>y?y:x;}
inline void Build_G()
{
map<pa,bool>::iterator it;
for (it=Edge.begin();it!=Edge.end();it++)
if (it->se)
Add(it->fi.fi,it->fi.se);
}
inline void Clear_G()
{
map<pa,bool>::iterator it;
for (it=Edge.begin();it!=Edge.end();it++)
if (it->se) it->se=false;
}
//================================================= void Dfs1(int u)
{
vis[u]=true; siz[u]=;
for (int i=head[u];i!=-;i=edge[i].next)
if (!vis[edge[i].to])
{
father[edge[i].to]=u;
dep[edge[i].to]=dep[u]+;
Dfs1(edge[i].to);
siz[u]+=siz[edge[i].to];
}
}
void Dfs2(int u,int chain)
{
num[u]=++stamp; top[u]=chain; vis[u]=true; int k=;
for (int i=head[u];i!=-;i=edge[i].next)
if (!vis[edge[i].to] && (siz[edge[i].to]>siz[k] || k==)) k=edge[i].to;
if (k==) return;
Dfs2(k,chain);
for (int i=head[u];i!=-;i=edge[i].next)
if (!vis[edge[i].to] && edge[i].to!=k) Dfs2(edge[i].to,edge[i].to);
} inline int Lca(int u,int v)
{
while (true)
{
if (top[u]==top[v]) return dep[u]>dep[v]?v:u;
if (dep[top[u]]>dep[top[v]]) u=father[top[u]]; else v=father[top[v]];
}
}
//================================================== inline void push_up(int o) {sum[o]=sum[o<<]+sum[o<<|];}
inline void Clr(int o) {clr[o]=; sum[o]=;}
inline void push_down(int o) {if (clr[o]) Clr(o<<),Clr(o<<|); clr[o]=;}
void Modify(int o,int l,int r,int p,int q)
{
if (l==p && r==q)
{
sum[o]=;
clr[o]=;
return;
}
push_down(o);
int mid=(l+r)>>;
if (q<=mid) Modify(o<<,l,mid,p,q);
if (p>=mid+) Modify(o<<|,mid+,r,p,q);
if (p<=mid && q>=mid+) Modify(o<<,l,mid,p,mid),Modify(o<<|,mid+,r,mid+,q);
push_up(o);
}
int Query(int o,int l,int r,int p,int q)
{
if (l==p && r==q) return sum[o];
push_down(o);
int mid=(l+r)>>;
if (q<=mid) return Query(o<<,l,mid,p,q);
if (p>=mid+) return Query(o<<|,mid+,r,p,q);
if (p<=mid && q>=mid+) return Query(o<<,l,mid,p,mid)+Query(o<<|,mid+,r,mid+,q);
}
void Build(int o,int l,int r)
{
if (l==r)
{
sum[o]=;
return;
}
int mid=(l+r)>>;
Build(o<<,l,mid),Build(o<<|,mid+,r);
push_up(o);
} //=================================================
void Tree_Modify(int u,int v)
{
while (top[u]!=top[v])
{
Modify(,,scc,num[top[u]],num[u]);
u=father[top[u]];
}
Modify(,,scc,num[v],num[u]);
}
int Tree_Query(int u,int v)
{
int ret=; while (top[u]!=top[v])
{
ret+=Query(,,scc,num[top[u]],num[u]);
u=father[top[u]];
}
ret+=Query(,,scc,num[v],num[u]);
return ret;
}
//=================================================
void Tarjan(int u,int fa)
{
Low[u]=Dfn[u]=++Stamp; Stack[++apex]=u;
for(int i=head[u];i!=-;i=edge[i].next)
if (edge[i].to!=fa)
{
int v=edge[i].to;
if(!Dfn[v])
{
Tarjan(v,u);
Low[u]=Min(Low[u],Low[v]);
if(Low[v]>Dfn[u])
{
scc++;
while(true) {int x=Stack[apex--]; Belong[x]=scc; if(x==v)break;}
}
}
else Low[u]=Min(Low[u],Dfn[v]);
}
if(fa<)
{
scc++;
while(true){int x=Stack[apex--]; Belong[x]=scc; if(x==u)break;}
}
}
//================================================= int main()
{
//freopen("c.in","r",stdin);
Get_Int(n),Get_Int(m);
for (int i=;i<=m;i++)
Get_Int(u),Get_Int(v),Edge[mp(u,v)]=true,Edge[mp(v,u)]=true; for (Q=;;Q++)
{
Get_Int(Op[Q].type); if (Op[Q].type==-) break;
Get_Int(Op[Q].u),Get_Int(Op[Q].v);
if (Op[Q].type==) Edge[mp(Op[Q].u,Op[Q].v)]=false,Edge[mp(Op[Q].v,Op[Q].u)]=false;
}
Q--;
stamp=Stamp=cnt=;
memset(head,-,sizeof(head));
memset(vis,false,sizeof(vis));
memset(Low,,sizeof(Low));
memset(Dfn,,sizeof(Dfn)); Build_G();
Tarjan(,-);
Clear_G();
for (int i=;i<=n;i++)
for (int j=head[i];j!=-;j=edge[j].next)
if (Belong[i]!=Belong[edge[j].to])
{
if (S.count(mp(Belong[i],Belong[edge[j].to]))==) continue;
S.insert(mp(Belong[i],Belong[edge[j].to]));
S.insert(mp(Belong[edge[j].to],Belong[i]));
V.pb(mp(Belong[i],Belong[edge[j].to]));
V.pb(mp(Belong[edge[j].to],Belong[i]));
} memset(head,-,sizeof(head));cnt=;
for (int i=;i<V.size();i++) Add(V[i].fi,V[i].se);
father[]=;dep[]=;
memset(vis,false,sizeof(vis)),Dfs1();
memset(vis,false,sizeof(vis)),Dfs2(,);
Build(,,scc);
for (int i=Q;i>=;i--)
{
int p=Belong[Op[i].u],q=Belong[Op[i].v];
if (Op[i].type==)
{
if (p==q) continue;
int t=Lca(p,q);
if (t==p)
{
int k=;
for (int j=head[t];j!=-;j=edge[j].next)
if (Lca(edge[j].to,q)==edge[j].to && father[t]!=edge[j].to) {k=edge[j].to; break;} Tree_Modify(q,k);
continue;
} if (t==q)
{
int k=;
for (int j=head[t];j!=-;j=edge[j].next)
if (Lca(edge[j].to,p)==edge[j].to && father[t]!=edge[j].to) {k=edge[j].to; break;}
Tree_Modify(p,k);
continue;
}
int r,s;
for (int j=head[t];j!=-;j=edge[j].next)
if (Lca(edge[j].to,p)==edge[j].to && father[t]!=edge[j].to) {r=edge[j].to; break;}
for (int j=head[t];j!=-;j=edge[j].next)
if (Lca(edge[j].to,q)==edge[j].to && father[t]!=edge[j].to) {s=edge[j].to; break;}
Tree_Modify(p,r),Tree_Modify(q,s);
} else
if (Op[i].type==)
{
if (p==q) {Ans[i]=; continue;}
int t=Lca(p,q);
if (t==p)
{
int k=;
for (int j=head[t];j!=-;j=edge[j].next)
if (Lca(edge[j].to,q)==edge[j].to && father[t]!=edge[j].to) {k=edge[j].to; break;}
Ans[i]=Tree_Query(q,k);
continue;
}
if (t==q)
{
int k=;
for (int j=head[t];j!=-;j=edge[j].next)
if (Lca(edge[j].to,p)==edge[j].to && father[t]!=edge[j].to) {k=edge[j].to; break;}
Ans[i]=Tree_Query(p,k);
continue;
} int r,s;
for (int j=head[t];j!=-;j=edge[j].next)
if (Lca(edge[j].to,p)==edge[j].to && father[t]!=edge[j].to) {r=edge[j].to; break;}
for (int j=head[t];j!=-;j=edge[j].next)
if (Lca(edge[j].to,q)==edge[j].to && father[t]!=edge[j].to) {s=edge[j].to; break;}
Ans[i]=Tree_Query(p,r)+Tree_Query(q,s);
}
}
for (int i=;i<=Q;i++)
if (Op[i].type==) Put_Int(Ans[i]);
return ;
}

傻逼树剖280+系列

BZOJ 1969 树链剖分+Tarjan缩点的更多相关文章

  1. BZOJ_4326_[NOIP2015]_运输计划_(二分+LCA_树链剖分/Tarjan+差分)

    描述 http://www.lydsy.com/JudgeOnline/problem.php?id=4326 给出一棵带有边权的树,以及一系列任务,任务是从树上的u点走到v点,代价为u到v路径上的权 ...

  2. BZOJ 4326 树链剖分+二分+差分+记忆化

    去年NOIP的时候我还不会树链剖分! 还是被UOJ 的数据卡了一组. 差分的思想还是很神啊! #include <iostream> #include <cstring> #i ...

  3. BZOJ 1036 && 树链剖分

    还是太弱啊..各种数据结构只听过名字却没有一点概念..树链剖分也在这个范畴..今天来进一步深化一下教育改革推进全民素质提高. 性质 忘了在哪里看到的一篇blog有一句话讲得非常好,树链剖分不是一种数据 ...

  4. bzoj 3083 树链剖分

    首先我们先将树提出一个根变成有根树,那么我们可以通过树链剖分来实现对于子树的最小值求解,那么按照当前的根和询问的点的相对位置关系我们可以将询问变成某个子树和或者除去某颗子树之后其余的和,前者直接询问区 ...

  5. bzoj 2243 树链剖分

    2013-11-19 16:21 原题传送门http://www.lydsy.com/JudgeOnline/problem.php?id=2243 树链剖分,用线段树记录该区间的颜色段数,左右端点颜 ...

  6. bzoj 4196 树链剖分 模板

    [Noi2015]软件包管理器 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 2135  Solved: 1232[Submit][Status][D ...

  7. BZOJ 4811 树链剖分+线段树

    思路: 感觉这题也可神了.. (还是我太弱) 首先发现每一位不会互相影响,可以把每一位分开考虑,然后用树链剖分或者LCT维护这个树 修改直接修改,询问的时候算出来每一位填0,1经过这条链的变换之后得到 ...

  8. BZOJ 4034 树链剖分

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=4034 题意:中文题面 思路:树链剖分入门题. 剖分后就是一个简单的区间更新和区间求和问题. ...

  9. BZOJ 2286 树链剖分+DFS序+虚树+树形DP

    第一次学习虚树,就是把无关的点去掉.S里维护一条链即可. #include <iostream> #include <cstring> #include <cstdio& ...

随机推荐

  1. json根据key取values

    function getJson(key, jsonObj) { for (var item in jsonObj) { if (item == key) { //item 表示Json串中的属性,如 ...

  2. JAVA基础知识之JDBC——ResultSet的滚动和更新(statement的额外参数)

    ResultSet不仅可以内存中的一张二维表一样保存statement执行SQL的结果集,还能通过结果集修改DB的数据.ResultSetMetaData则可以用来获得ResultSet对象的相关信息 ...

  3. 查看占用cpu和内存最多的进程

    linux下获取占用CPU资源最多的10个进程,可以使用如下命令组合: ps aux|head -;ps aux|grep -v PID|sort -rn -k +|head linux下获取占用内存 ...

  4. centos 服务开机启动设置

    建立服务文件以nginx 为例 vim /lib/systemd/system/nginx.service 在nginx.service 中插入一下内容 [Unit] Description=ngin ...

  5. JQ写简单的伸缩菜单(内附效果图和源代码)

    效果如图: JQ代码就那么几句, <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "h ...

  6. 反编译CHM文件

    1.进入dos 2.输入 HH.EXE -decompile <输出路径> <目标chm文件> 例如:hh.exe -decompile d:\heihei D:\123.ch ...

  7. linux应用程序开发-文件编程-库函数

    ---恢复内容开始--- c库函数文件操作独立于具体的系统平台,可移植性较好. 库函数-创建和打开 FILE*fopen(const char*filename,const char*mode) mo ...

  8. div 一段时间后自动隐藏

    一.div弹出后自动消失 这里并没有删除 setTimeout(function(){$(".alert").hide();},2000); 直接在js文件中需要的地方添加执行这段 ...

  9. C++ do{...}while(0)的好处

    在开源软件里面经常可以看到这样的写法. #define X(a) do { f1(a); f2(a); } while(0) 1. 主要作用是放在宏定义里面,避免宏带来的语法问题. 比如 #defin ...

  10. 将回车键转tab键

    //功能:将回车键转tab键$(function () {$('input:text:first').focus();var $enter = $("input[type=text],but ...