231E - Cactus

给一个10^5个点的无向图,每个点最多属于一个环,规定两点之间的简单路:从起点到终点,经过的边不重复

给10^5个询问,每个询问两个点,问这两个点之间有多少条简单路。

挺综合的一道题目,无向图连通分量,缩点,LCA 都考察到了。。

因为每个点最多属于一个环,因此把所有环缩点,就可以得到一棵树

然后对于每个询问,用LCA查找从起点到终点有多少个环

并查集处理的时候挂了一发,注意LCA时合并两个并查集,根节点深度小的作为父亲。。

#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<set>
#include<map>
#include<stack>
#include<vector>
#include<queue>
#include<string>
#include<sstream>
#define eps 1e-9
#define ALL(x) x.begin(),x.end()
#define INS(x) inserter(x,x.begin())
#define rep(i,j,k) for(int i=j;i<=k;i++)
#define MAXN 100005
#define MAXM 400005
#define INF 0x3fffffff
#define PB push_back
#define MP make_pair
#define X first
#define Y second
#define clr(x,y) memset(x,y,sizeof(x));
using namespace std;
typedef long long LL;
int i,j,k,n,m,x,y,T,big,cas,len;
bool flag; int edge,head[MAXN],bin[MAXN],headS[MAXN],edgeS,vis[MAXN],d[MAXN],id[MAXN],num[MAXN];
struct edgenode
{
int to,next,flag;
} G[MAXM],S[MAXM]; void add_edge(int x,int y)
{
G[edge].to=y;
G[edge].flag=;
G[edge].next=head[x];
head[x]=edge++;
} void add_edgeS(int x,int y)
{
S[edgeS].to=y;
S[edgeS].flag=;
S[edgeS].next=headS[x];
headS[x]=edgeS++;
} int fa[MAXN];
int findset(int x)
{
return x==fa[x]?x:fa[x]=findset(fa[x]);
}
void unionset(int x,int y)
{
fa[findset(x)]=findset(y);
} int dfn[MAXN],low[MAXN],time;
void dfs(int u,int fa)
{
vis[u]=;
dfn[u]=low[u]=++time;
for (int i=head[u];i!=-;i=G[i].next)
{
int v=G[i].to;
if (v!=fa && vis[v]==)
{
low[u]=min(low[u],dfn[v]);
} if (!vis[v])
{
dfs(v,u);
low[u]=min(low[u],low[v]);
if (low[v]>dfn[u]) G[i].flag=;
}
}
vis[u]=;
} void dive(int u,int scc)
{
id[u]=scc;
vis[u]=;
num[scc]++;
for (int i=head[u];i!=-;i=G[i].next)
{
if (!G[i].flag && !vis[G[i].to])
dive(G[i].to,scc);
}
} void dis(int u,int dep)//记录当前节点到根节点有多少个“环”
{
vis[u]=;
d[u]=dep;
for (int i=headS[u];i!=-;i=S[i].next)
{
int v=S[i].to;
if (!vis[v])
{
if (num[v]>) dis(v,dep+);
else dis(v,dep);
}
}
} vector<pair<int,int> > Q[MAXN];
int ans[MAXN];
void tarjan(int u)
{
vis[u]=true;
for (int i=;i<Q[u].size();i++)
{
int v=Q[u][i].X,id=Q[u][i].Y;
if (vis[v])
{
int com=findset(v);
ans[id]=d[u]+d[v]-*d[com];
if (num[com]>) ans[id]++;
}
} for (int i=headS[u];i!=-;i=S[i].next)
{
int v=S[i].to;
if (!vis[v])
{
tarjan(v);
unionset(v,u);
}
}
} int main()
{
memset(head,-,sizeof(head));
edge=;
memset(headS,-,sizeof(headS));
edgeS=;
scanf("%d%d",&n,&m);
while (m--)
{
scanf("%d%d",&x,&y);
add_edge(x,y);
add_edge(y,x);
} dfs(,-); memset(vis,,sizeof(vis));
int scc=;
for (int i=;i<=n;i++)
{
if (!vis[i]) dive(i,scc++);
} for (i=;i<=n;i++)
{
for (int j=head[i];j!=-;j=G[j].next)
{
int v=G[j].to;
if (id[i]!=id[v])
{
add_edgeS(id[i],id[v]);
add_edgeS(id[v],id[i]);
}
}
} int q;
scanf("%d",&q);
for (i=;i<q;i++)
{
scanf("%d%d",&x,&y);
x=id[x];y=id[y];
Q[x].PB(MP(y,i));
Q[y].PB(MP(x,i));
} memset(vis,,sizeof(vis));
if (num[]>) dis(,); else dis(,); memset(vis,,sizeof(vis));
for (i=;i<=n;i++) fa[i]=i;
tarjan(); bin[]=;
for(int i=;i<MAXN;i++)
bin[i]=bin[i-]*%;
for (int i=;i<q;i++)
{
printf("%d\n",bin[ans[i]]);
}
return ;
}

Codeforces 231E - Cactus的更多相关文章

  1. Cactus CodeForces - 231E (无向图缩环)

    大意: 给定无向图, 每个点最多属于一个简单环, 多组询问, 求给定起点终点, 有多少条简单路径. 先缩环, 然后假设两点树上路径经过$cnt$个环, 那么答案就为$2^{cnt}$. 要注意缩环建树 ...

  2. Codeforces 980F Cactus to Tree 仙人掌 Tarjan 树形dp 单调队列

    原文链接https://www.cnblogs.com/zhouzhendong/p/CF980F.html 题目传送门 - CF980F 题意 给定一个 $n$ 个节点 $m$ 条长为 $1$ 的边 ...

  3. Codeforces Round #143 (Div. 2) E. Cactus 无向图缩环+LCA

    E. Cactus   A connected undirected graph is called a vertex cactus, if each vertex of this graph bel ...

  4. Codeforces 1236F - Alice and the Cactus(期望+分类讨论)

    Codeforces 题面传送门 & 洛谷题面传送门 期望好题. 首先拆方差: \[\begin{aligned} &E((x-E(x))^2)\\ =&E(x^2)-2E(x ...

  5. Codeforces 856D - Masha and Cactus(树链剖分优化 dp)

    题面传送门 题意: 给你一棵 \(n\) 个顶点的树和 \(m\) 条带权值的附加边 你要选择一些附加边加入原树中使其成为一个仙人掌(每个点最多属于 \(1\) 个简单环) 求你选择的附加边权值之和的 ...

  6. [Codeforces]856D - Masha and Cactus

    题目大意:给出一棵树和若干条可以加入的边,要求加入若干条边使图是仙人掌并且加入的边权和最大,仙人掌定义为没有一个点属于超过1个环.(n,m<=200,000) 做法:这题的仙人掌跟平时见到的不太 ...

  7. python爬虫学习(5) —— 扒一下codeforces题面

    上一次我们拿学校的URP做了个小小的demo.... 其实我们还可以把每个学生的证件照爬下来做成一个证件照校花校草评比 另外也可以写一个物理实验自动选课... 但是出于多种原因,,还是绕开这些敏感话题 ...

  8. 【Codeforces 738D】Sea Battle(贪心)

    http://codeforces.com/contest/738/problem/D Galya is playing one-dimensional Sea Battle on a 1 × n g ...

  9. 【Codeforces 738C】Road to Cinema

    http://codeforces.com/contest/738/problem/C Vasya is currently at a car rental service, and he wants ...

随机推荐

  1. 4d tensor

    偶然在一个ppt中看到了如下关于tensor的解释,清晰明白,所以post在这里,以备后续查看 根据这个理解: theano中的input(4d tensor):[mini-batch size, n ...

  2. 改变UITextField placeHolder色彩、字体

    改变UITextField placeHolder颜色.字体 我们有时需要定制化UITextField对象的风格,可以添加许多不同的重写方法,来改变文本字段的显示行为.这些方法都会返回一个CGRect ...

  3. KMP字符串模式匹配详解(转)

    来自CSDN     A_B_C_ABC 网友 KMP字符串模式匹配通俗点说就是一种在一个字符串中定位另一个串的高效算法.简单匹配算法的时间复杂度为O(m*n);KMP匹配算法.可以证明它的时间复杂度 ...

  4. MockupBuilder

    玩一下,想起了以前公司产品经理作的些事了...

  5. 【BZOJ1030】[JSOI2007]文本生成器

    [题意] 给定一些单词,我们定义一篇可读文章至少包含一个这样的单词,求长度为M的可读文章总数. [分析] 用前几题的方法可以求长度为M的不可读的文章总数Sum,所以我们可以用26^M-Sum来求出可读 ...

  6. YII model模型和登陆详解

    模型是 CModel 或其子类的实例.模型用于保持数据以及与其相关的业务逻辑. 模型是单独的数据对象.它可以是数据表中的一行,或者一个用户输入的表单. 数据对象的每个字段对应模型中的一个属性.每个属性 ...

  7. bzoj3143

    之前我们曾经用dp解决过数学期望问题,这次我们用的是解方程的方法首先在编号之前,肯定要求出每条边的期望经过次数然后可以转化为求边端点的期望次数这种做法我一开始接触是noip2013的初赛问题求解,是类 ...

  8. 重装VS2010时出现未能正确加载 "radlangsvc.package,radlangsvc.vs...

    解决办法: 开始-->所有程序--Microsoft visual studio2010-->visual studio tools-->visual studio 2010命令提示 ...

  9. HDU 5922 Minimum’s Revenge 【模拟】 (2016CCPC东北地区大学生程序设计竞赛)

    Minimum's Revenge Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others ...

  10. 在word 2013中输入latex公式

    注意:版权所有,转载请注明出处 向word输入LaTeX公式,插件有很多,前面在使用的是一个叫做Aurora的插件,结果不是免费的,用了一段时间就要收费是,所以就不用了,从网上找到别人的介绍,可以使用 ...