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 ...
随机推荐
- 业界良心:Square开源Viewfinder,25万行代码全公布!
http://www.csdn.net/article/2014-05-06/2819633-square-open-sources-viewfinder https://github.com/vie ...
- word的不同章节之间添加不同的页眉
1.点击空百处 2. 在页面布局中,找到分隔符,选择”连续“选项,即在空白处插入分隔符 特别注意:这里分隔符会出现换行现象,请选择空白处,不要影响原先布局 3. 当编辑下一个页眉时,点击“链接到前一条 ...
- Welcome to JimmyCheung's blog!
博客开通,写写学习笔记,写写心情,写写生活中的点点滴滴~ 有钱的捧个钱场嘞,没钱的贡献个点击量,新鲜的博客出炉咯,来五毛钱的博文呗~ By Jimmy 2014.09.16
- Spring MVC和Struts2的区别
1. 机制:spring mvc的入口是servlet,而struts2是filter,这样就导致了二者的机制不同. 2. 性能:spring会稍微比struts快.spring mvc是基于方法的设 ...
- Matlab读取cifar10 train_quick.sh输出txt中信息
感谢 网友 Vagrant的提醒.之前 一直就看个最后的accuracy.这个应该并不靠谱.最好把说有的信息都看一下.而一个一个看.根本记不住.只能把数据读取在图片中显示一下,才比较直观. 本文就是读 ...
- Python on Android
Python on Android Posted on April 29, 2015 by Alexander Taylor There are an increasing number of r ...
- Android 使用HTTP(get和post)方式登陆服务器
package com.wuyou.submittoserver; import android.os.Bundle; import android.support.v7.app.ActionBarA ...
- ArtisticStyle----很好用的C/C++样式格式化工具
下载地址:http://srgb.googlecode.com/files/AStyle_2.02_windows.7z 把astyle.exe 复制到 C:\WINDOWS 目录里,省的指定路径VC ...
- 代理Delegate的小应用(代理日期控件和下拉框)
前言 在平时关于表格一类的的控件使用中,不可避免需要修改每个Item的值,通过在Item中嵌入不同的控件对编辑的内容进行限定,然而在表格的Item中插入的控件始终显示,当表格中item项很多的时候,会 ...
- linux下USB串口,minicom
[一].驱动相关说明: 如果直接使用串口线,而没有用到USB转串口设备,就不需要安装驱动. 如果使用了USB转串口,一般情况下也不需要安装驱动了,目前linux系统已经包含了该驱动,可以自动识别,亦可 ...