Codeforces 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的更多相关文章
- Cactus CodeForces - 231E (无向图缩环)
大意: 给定无向图, 每个点最多属于一个简单环, 多组询问, 求给定起点终点, 有多少条简单路径. 先缩环, 然后假设两点树上路径经过$cnt$个环, 那么答案就为$2^{cnt}$. 要注意缩环建树 ...
- Codeforces 980F Cactus to Tree 仙人掌 Tarjan 树形dp 单调队列
原文链接https://www.cnblogs.com/zhouzhendong/p/CF980F.html 题目传送门 - CF980F 题意 给定一个 $n$ 个节点 $m$ 条长为 $1$ 的边 ...
- 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 ...
- Codeforces 1236F - Alice and the Cactus(期望+分类讨论)
Codeforces 题面传送门 & 洛谷题面传送门 期望好题. 首先拆方差: \[\begin{aligned} &E((x-E(x))^2)\\ =&E(x^2)-2E(x ...
- Codeforces 856D - Masha and Cactus(树链剖分优化 dp)
题面传送门 题意: 给你一棵 \(n\) 个顶点的树和 \(m\) 条带权值的附加边 你要选择一些附加边加入原树中使其成为一个仙人掌(每个点最多属于 \(1\) 个简单环) 求你选择的附加边权值之和的 ...
- [Codeforces]856D - Masha and Cactus
题目大意:给出一棵树和若干条可以加入的边,要求加入若干条边使图是仙人掌并且加入的边权和最大,仙人掌定义为没有一个点属于超过1个环.(n,m<=200,000) 做法:这题的仙人掌跟平时见到的不太 ...
- python爬虫学习(5) —— 扒一下codeforces题面
上一次我们拿学校的URP做了个小小的demo.... 其实我们还可以把每个学生的证件照爬下来做成一个证件照校花校草评比 另外也可以写一个物理实验自动选课... 但是出于多种原因,,还是绕开这些敏感话题 ...
- 【Codeforces 738D】Sea Battle(贪心)
http://codeforces.com/contest/738/problem/D Galya is playing one-dimensional Sea Battle on a 1 × n g ...
- 【Codeforces 738C】Road to Cinema
http://codeforces.com/contest/738/problem/C Vasya is currently at a car rental service, and he wants ...
随机推荐
- 调优UWSGI,后台启动,热更改PY,杜绝502
记得加启动参数: --daemonize /var/log/uwsgi.log --post-buffering 32768 --buffer-size 32768 reload.set #!/bin ...
- Android SmartImageView框架的简单实用
特征:根据URL地址装载图像:支持装载通讯录中的图像:支持异步装载:支持缓存: 这个是作者的项目主页,有使用方法.http://loopj.com/android-smart-image-view/ ...
- Scanner 与 Readable 的read()方法
Readable接口中的read()方法实现了将字符串读入charBuffer中,但是只有在需要输出的时候才会调用. Scanner是文本扫描器类,利用Scanner扫描并输出charBuffer中的 ...
- 机器安装第二个tomcat ,出现报错如何解决
1.本机安装第二个 tomcat 后,出现 报错如下图所示 最后解决办法 是 在安装的时候 ,windows 服务名称 和 另一个tomcat 起不一样的 名称就可以了 如下图
- Apache 整合 Tomcat (首先Apache 发布的是PHP项目,占用端口80,tomcat 发布的是Java 项目,占用端口8080)
情况简介: Apache 整合 Tomcat (首先Apache 发布的是PHP项目,占用端口80,tomcat 发布的是Java 项目,占用端口8080),而现在是虚拟出来两个域名(希望这两个域名都 ...
- Unity3D学习笔记-------小地图制作
制作小地图首先需要两个贴图:第一个贴图是小地图的背景贴图,它应当是从y轴向下俯视截取的贴图:第二个贴图是主角位置贴图,它应当是在背景贴图之上的小型矩形. 1 using UnityEngine; 2 ...
- HDOJ/HDU 1321 Reverse Text(倒序输出~)
Problem Description In most languages, text is written from left to right. However, there are other ...
- zabbix web场景模拟监控配置
一,zabbix2.2.3 VMware Vsphere exsi监控配置步骤, 1,添加监控主机 2,添加聚集macro;{$PASSWORD} = yoodo.com{$URL} = http:/ ...
- 详解C#中System.IO.File类和System.IO.FileInfo类的用法
System.IO.File类和System.IO.FileInfo类主要提供有关文件的各种操作,在使用时需要引用System.IO命名空间.下面通过程序实例来介绍其主要属性和方法. (1) 文件打开 ...
- Linux安装sonarQube
安装sonarQube之前,需要先安装JDK和mysql 服务器/home/azrlnx04/下创建三个文件夹,/java ./mysql. /sonar 一:安装JDK (1)打开http://ww ...