luogu P4129 [SHOI2006]仙人掌
题目描述
仙人掌图(cactus)是一种无向连通图,它的每条边最多只能出现在一个简单回路(simple cycle)里面。从直观上说,可以把仙人掌图理解为允许存在回路的树。但是仙人掌图和树之间有个本质的不同,仙人掌图可以拥有多个支撑子图(spanning subgraph),而树的支撑子图只有一个(它自身),我们把仙人掌图的支撑子图的数目称为“仙人数”。你的任务就是计算给定图的“仙人数”。
一些关于仙人掌图的举例:
第一张图是一个仙人掌图,第二张图的边(2,3)在两个不同的回路里面,所以不是仙人掌图,第三张图不是一个连通图,所以也不是仙人掌图。
以下是对一些术语的解释:
简单回路(simple cycle):简单回路是原图的一条路径,这条路径的边集构成了回路,回路中顶点只能出现一次。比如对于上例中第二个图来说,它一共有三个简单回路,分别是(4,3,2,1,6,5)、(7,8,9,10,2,3)和(4,3,7,8,9,10,2,1,6,5)
支撑子图(spanning subgraph):支撑子图也是原图的子图,这种子图可以比原来少一些边,但是不能破坏图的连通性,也不能去除原来图上的任何顶点。“支撑”的概念类似于我们熟知的“最小支撑树”,对于上例中的第一张图来说,任意去除回路I中的图或回路II中的一条边都能构成一个支撑子图,所以它的支撑子图一共有6 + 4 + 6 × 4 + 1 = 35种(注意图自身也是自己的一个子图)
输入格式
输入文件的第一行是两个整数n和m(1≤n≤20000, 0≤m≤1000)。n代表图的顶点数,顶点的编号总是从1到n表示的。
接下来一共有m行。每行都代表了图上的一条路径(注意:这里所表示的一条路径可不一定是一条回路)。这些行的格式是首先有一个整数ki(2≤ki≤1000)代表这条路径通过了几个顶点,接下来是ki个在1到n之间的数字,其中每个数字代表了图上的一个顶点,相邻的顶点之间就定义了一条边。一条路径上可能通过一个顶点好几次,比如对于第一个例子,第一条路径从2经过3,又从8返回到了3,但是我们保证所有的边都会出现在某条路径上,而且不会重复出现在两条路径上,或者在一条路径上出现两次。
输出格式
输出这张图的“仙人数”,如果它不是一张仙人掌图,输出0。注意最后的答案可能是一个很大很大的数。
输入输出样例
14 3
9 1 2 3 4 5 6 7 8 3
7 2 9 10 11 12 13 10
2 2 14
35
10 2
7 1 2 3 4 5 6 1
6 3 7 8 9 10 2
0
5 1
4 1 2 3 4
0 思路:注意高精度和与点双不同的是判简单环边数即可
typedef long long LL;
typedef pair<LL, LL> PLL;
const LL bas = ; struct Big_Number {
LL a[],len;
void init() {
len = ;
memset(a, , sizeof a);
a[] = ;
}
void mul(LL val) {
for (int i = ; i < len; i++) {
a[i] = a[i] * val;
}
for (int i = ; i < len; i++){
a[i + ] += a[i] / bas;
a[i] %= bas;
}
while (a[len]) {
a[len + ] = a[len] / bas;
a[len] %= bas;
len++;
}
}
void print() {
printf("%lld", a[len - ]);
for (int i = len - ; i >= ; i--) {
printf("%.8lld", a[i]);
}
printf("\n");
}
} ans; const int maxm = 2e6+;
const int maxn = 2e5+; int head[maxm], edgecnt, dfn[maxn], low[maxn], bcc_cnt, bccnum[maxn], dfs_clock, s[maxm], top, vis[maxn], num;
LL bcc[maxn];
bool ok = true; struct edge{
int u, v, nex;
} edges[maxm]; void addedge(int u, int v) {
edges[++edgecnt].u = u;
edges[edgecnt].v = v;
edges[edgecnt].nex = head[u];
head[u] = edgecnt;
} void dfs(int u, int fa) {
vis[u] = ;
++num;
for(int i = head[u]; i; i = edges[i].nex) {
int v = edges[i].v;
if(v == fa) continue;
if(!vis[v])
dfs(v, u);
}
} void tarjan(int u, int fa) {
dfn[u] = low[u] = ++dfs_clock;
int child = , v;
for(int i = head[u]; i; i = edges[i].nex) {
v = edges[i].v;
if(v == fa) continue;
if(!dfn[v]) {
s[++top] = i;
tarjan(v, u);
low[u] = min(low[u], low[v]);
if(low[v] >= dfn[u]) {
++bcc_cnt;
LL vet = ;
while(true) {
int num = s[top--];
if(bccnum[edges[num].v] != bcc_cnt) {
vet++;
bccnum[edges[num].v]=bcc_cnt;
} else ok = false;
if(edges[num].u == u && edges[num].v == v) break;
}
if(ok && vet>)
ans.mul(vet+);
}
} else if(dfn[v] < dfn[u]){
s[++top] = i;
low[u] = min(low[u], dfn[v]);
}
}
} void run_case() {
int n, m, u, v, t;
ans.init();
cin >> n >> m;
for(int i = ; i <= m; ++i) {
cin >> t;
t--;
cin >> u;
while(t--) {
cin >> v;
addedge(u, v), addedge(v, u);
u = v;
}
}
dfs(n, -);
if(n != num) {
cout << "";
return;
}
tarjan(, -);
if(!ok) cout << "";
else
ans.print();
} int main() {
//ios::sync_with_stdio(false), cin.tie(0);
run_case();
return ;
}
(自用板,记录每一个点双和割点
luogu P4129 [SHOI2006]仙人掌的更多相关文章
- 2018.10.29 洛谷P4129 [SHOI2006]仙人掌(仙人掌+高精度)
传送门 显然求出每一个环的大小. Ans=∏i(siz[i]+1)Ans=\prod_i(siz[i]+1)Ans=∏i(siz[i]+1) 注意用高精度存答案. 代码: #include<b ...
- Luogu 4244 [SHOI2008]仙人掌图
BZOJ 1023 如果我们把所有的环都缩成一个点,那么整张图就变成了一棵树,我们可以直接$dp$算出树的直径. 设$f_x$表示$x$的子树中最长链的长度,那么对于$x$的每一个儿子$y$,先用$f ...
- pkuwc 前的任务计划
菜鸡 wxw 的计划(肯定会咕咕咕 12.27 luogu P4244 [SHOI2008]仙人掌图 II(咕咕咕 luogu P4246 [SHOI2008]堵塞的交通 (没有咕! luogu P1 ...
- luogu P3180 [HAOI2016]地图 仙人掌 线段树合并 圆方树
LINK:地图 考虑如果是一棵树怎么做 权值可以离散 那么可以直接利用dsu on tree+树状数组解决. 当然 也可以使用莫队 不过前缀和比较难以维护 外面套个树状数组又带了个log 套分块然后就 ...
- luogu 2478 [SDOI2010]城市规划 仙人掌上dp.
LINK:城市规划 以前ls 让写的时候由于看不懂题目+以为在图中的环上dp非常困难所以放弃治疗了. 现在终于能把题目看懂了 泪目... 题目其实就是在说 给出一张图这个有一个非常好的性质 满足每个点 ...
- ●洛谷P3687 [ZJOI2017]仙人掌
题链: https://www.luogu.org/problemnew/show/P3687题解: 计数DP,树形DP. (首先对于这个图来说,如果初始就不是仙人掌,那么就直接输出0) 然后由于本来 ...
- 图论杂项细节梳理&模板(虚树,圆方树,仙人掌,欧拉路径,还有。。。)
orzYCB 虚树 %自为风月马前卒巨佬% 用于优化一类树形DP问题. 当状态转移只和树中的某些关键点有关的时候,我们把这些点和它们两两之间的LCA弄出来,以点的祖孙关系连成一棵新的树,这就是虚树. ...
- LOJ #2547 Luogu P4517「JSOI2018」防御网络
好像也没那么难写 LOJ #2547 Luogu P4517 题意 在一棵点仙人掌中等概率选择一个点集 求选出点集的斯坦纳树大小的期望 定义点仙人掌为不存在一个点在多个简单环中的连通图 斯坦纳树为在原 ...
- 仙人掌&圆方树
仙人掌&圆方树 Tags:图论 [x] [luogu4320]道路相遇 https://www.luogu.org/problemnew/show/P4320 [ ] [SDOI2018]战略 ...
随机推荐
- ECMAScript 6 和数组的新功能
Array. @@iterator 返回一个包含数组键值对的迭代器对象,可以通过同步调用得到数组元素的键值对 copyWithin 复制数组中一系列元素到同一数组指定的起始位置 entries 返回包 ...
- 洛谷 CF798C Mike and gcd problem
嗯... 题目链接:https://www.luogu.org/problemnew/show/CF798C 这道题首先要会写gcd..也类似一种找规律吧... 问题的操作是在两个数的基础上进行的: ...
- Live2d技术
保存一些关于Live2d技术的博文或模型资源,有空研究研究. 什么是 live2d?:https://baike.baidu.com/item/Live2D/8496493 1.https://www ...
- 关于编译QT官方的MQTT库.
先放一位博主的资料,参阅了其中资料,表示感谢: https://www.cnblogs.com/yexiaopeng/p/8542894.html ########################## ...
- el-dialog 如何自定义大小样式
使用属性:custom-class 然后在css中根据这个类型编写指定的样式即可(比如宽高) 举例:
- git合并分支到主干
1.从当前分支切换主干 git checkout master 2.更新主干内容到本地 git pull 4.提交分支,并将分支merge到主干 git merge dev 5: i键后输入备注 输 ...
- 读取npz,并显示图像
import numpy as npimport osimport matplotlib.pyplot as pltimport sysimport cv2 a = np.load('/home/wg ...
- nginx的addition模块在响应的前后报文添加内容与变量的运行原理
nginx默认未编译此模块:让nginx编译启用此模块 ./configure --prefix=/data/web --sbin-path=/usr/bin --user=nginx --group ...
- 使用eclipse创建一个简单的Java Web应用程序
关于Java JDK/JRE.Tomcat的配置等等都没什么好说的,主要记录一下使用Eclipse创建web工程时的一些点以及说一说自己用IDEA的创建失败的过程(IDEA没运行成功...暂时不想弄了 ...
- node.js中的事件轮询Event Loop
任务队列/事件队列 "任务队列"是一个事件的队列,IO设备完成一项任务,就在"任务队列"中添加一个事件,表示相关的异步任务可以进入"执行栈" ...