题目链接

BZOJ5315

题解

题目好吓人= =点仙人掌 + 斯坦纳树

我们只需求出对于所有选点的方案的斯坦纳树边长总和

\(n\)那么大当然不能状压,但是考虑一下如果这是一棵树,一个方案的贡献就是连接这些点的所有边

我们可以考虑计算每条边的贡献

一条边在树上有贡献,当且仅当它两端的树都存在被选择的点

那么这条边\((u,v)\)贡献就是

\[(2^{siz[u]} - 1)(2^{siz[v] - 1})
\]

其中\(siz[u]\)表示断开这条边后\(u\)一侧的树大小

如果放到仙人掌上呢?

对于割边,和树是一样的

我们只需计算每个环的贡献

考虑我们对于一个环,选择了其中\(K\)个点所在外向树,那么就有连接\(K\)个点的环上的\(K\)段边,我们一定是除去最长那一条

所以我们断环为链,设\(f[i][j][k]\)为选择了区间\([i,j]\)的外向树【意味着端点必选,中间不一定选,区间外一定不选】,\([i,j]\)中最大距离为\(k\)的方案数

那么有,即考虑最后一段的长度

\[f[i][j][k] = (2^{siz[j]} - 1)(\sum\limits_{x = 0}^{k}f[i][j - k][x] + \sum\limits_{x = j - k + 1}^{j - 1}f[i][x][k])
\]

直接转移是\(O(n^4)\)的,常数很小数据很水可以跑过。。。

当然可以前缀和优化成\(O(n^3)\)

【其实是我前缀和写炸了,直接交一波暴力转移竟然\(A\)了。。。】

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<map>
#define Redge(u) for (int k = h[u],to; k; k = ed[k].nxt)
#define REP(i,n) for (int i = 1; i <= (n); i++)
#define mp(a,b) make_pair<int,int>(a,b)
#define cls(s) memset(s,0,sizeof(s))
#define cp pair<int,int>
#define LL long long int
using namespace std;
const int maxn = 205,maxm = 100005,INF = 1000000000,P = 1000000007;
inline int read(){
int out = 0,flag = 1; char c = getchar();
while (c < 48 || c > 57){if (c == '-') flag = -1; c = getchar();}
while (c >= 48 && c <= 57){out = (out << 3) + (out << 1) + c - 48; c = getchar();}
return out * flag;
}
int h[maxn],ne = 1;
struct EDGE{int to,nxt;}ed[maxm];
inline void build(int u,int v){
ed[++ne] = (EDGE){v,h[u]}; h[u] = ne;
ed[++ne] = (EDGE){u,h[v]}; h[v] = ne;
}
int n,m;
inline int qpow(int a,int b){
int re = 1;
for (; b; b >>= 1,a = 1ll * a * a % P)
if (b & 1) re = 1ll * re * a % P;
return re;
}
int dfn[maxn],low[maxn],siz[maxn],fa[maxn],cnt,sum;
int v[maxn],K;
LL f[maxn][maxn][maxn],D[maxn][maxn][maxn],S[maxn][maxn][maxn],ans,bin[maxn];
void DP(int rt,int u){
K = 0; int tot = 0;
for (int i = u; i != rt; i = fa[i]){
v[++K] = siz[i];
siz[rt] += siz[i];
tot += siz[i];
}
v[++K] = sum - tot;
cls(f);
for (int l = 1; l <= K; l++)
for (int r = l; r <= K; r++)
for (int k = 0; k <= r - l; k++){
if (l == r){
if (k == 0) f[l][r][k] = bin[v[l]] - 1;
continue;
}
int d = 0,s = 0;
for (int i = 0; i <= k; i++) d = (d + f[l][r - k][i]) % P;
for (int i = r - k + 1; i < r; i++) s = (s + f[l][i][k]) % P;
f[l][r][k] = (bin[v[r]] - 1) * (d + s) % P;
ans = (ans + 1ll * (K - max(K - r + l,k)) * f[l][r][k] % P) % P;
}
}
void dfs(int u){
dfn[u] = low[u] = ++cnt; siz[u] = 1;
Redge(u) if ((to = ed[k].to) != fa[u]){
if (!dfn[to]){
fa[to] = u; dfs(to);
low[u] = min(low[u],low[to]);
}
else low[u] = min(low[u],dfn[to]);
if (low[to] > dfn[u]){
ans = (ans + 1ll * (bin[siz[to]] - 1) * (bin[sum - siz[to]] - 1) % P) % P;
siz[u] += siz[to];
}
}
Redge(u) if (fa[to = ed[k].to] != u && dfn[u] < dfn[to])
DP(u,to);
}
int main(){
bin[0] = 1; for (int i = 1; i <= 200; i++) bin[i] = bin[i - 1] * 2ll % P;
n = read(); m = read();
while (m--) build(read(),read());
sum = n; dfs(1);
ans = ans * qpow(bin[n],P - 2) % P;
printf("%lld\n",ans);
return 0;
}

BZOJ5315 [JSOI2018]防御网络 【仙人掌 + dp】的更多相关文章

  1. bzoj5315/luoguP4517 [JSOI2018]防御网络(仙人掌,dp)

    bzoj5315/luoguP4517 防御网络(仙人掌,dp) bzoj Luogu 题目描述略(太长了) 题解时间 本题和斯坦纳树无关. 题面保证了是一个仙人掌...? 但这个环之间甚至交点都没有 ...

  2. 洛谷P4517 [JSOI2018]防御网络(dp)

    题面 传送门 题解 翻译一下题意就是每次选出一些点,要用最少的边把这些点连起来,求期望边数 我也不知道为什么反正总之就是暴力枚举太麻烦了所以我们考虑贡献 如果一条边是割边,那么它会在图里当且仅当两边的 ...

  3. 【BZOJ5315】[JSOI2018]防御网络(动态规划,仙人掌)

    [BZOJ5315][JSOI2018]防御网络(动态规划,仙人掌) 题面 BZOJ 洛谷 题解 显然图是仙人掌. 题目给了斯坦纳树就肯定不是斯坦纳树了,,,, 总不可能真让你\(2^n\)枚举点集再 ...

  4. bzoj 5315: [Jsoi2018]防御网络

    Description Solution 考虑每一条边的贡献 对于树边,如果两边各存在一个点,那么有贡献,总贡献就是 \((2^{size}-1)*(2^{n-size}-1)\) 分别对应两边的 \ ...

  5. 【BZOJ-1952】城市规划 [坑题] 仙人掌DP + 最大点权独立集(改)

    1952: [Sdoi2010]城市规划 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 73  Solved: 23[Submit][Status][ ...

  6. 【BZOJ-4316】小C的独立集 仙人掌DP + 最大独立集

    4316: 小C的独立集 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 57  Solved: 41[Submit][Status][Discuss] ...

  7. BZOJ1023: [SHOI2008]cactus仙人掌图(仙人掌dp)

    Time Limit: 1 Sec  Memory Limit: 162 MBSubmit: 3467  Solved: 1438[Submit][Status][Discuss] Descripti ...

  8. 【BZOJ1487】[HNOI2009]无归岛(仙人掌 DP)

    题目: BZOJ1487 分析: 题目中给定的图一定是一棵仙人掌(每条边最多属于一个环),证明如下: 先考虑单独一个岛的情况.第一,一个岛一定是一张「弦图」,即任意一个大小超过 3 的环都至少有 1 ...

  9. bzoj4316小C的独立集(dfs树/仙人掌+DP)

    本题有两种写法,dfs树上DP和仙人掌DP. 先考虑dfs树DP. 什么是dfs树?其实是对于一棵仙人掌,dfs后形成生成树,找出非树边(即返祖边),然后dfs后每条返祖边+其所覆盖的链构成了一个环( ...

随机推荐

  1. 我们一起学习WCF 第二篇WCF承载多个接口

    前言:现在王大叔养了大批猪,赚了很多钱.但是最近发现养鸡也可以赚很多钱,他就像扩展业务开始养鸡.又过两年他发现市场对狗的需求量很大,他开始养狗.那么他改怎么做呢,不可能去修改猪住的地方把鸭子和狗放里面 ...

  2. javaweb(三十七)——获得MySQL数据库自动生成的主键

    测试脚本如下: 1 create table test1 2 ( 3 id int primary key auto_increment, 4 name varchar(20) 5 ); 测试代码: ...

  3. [.NET] 使用HttpClient操作HFS (HTTP File Server)

    前言 本篇文章介绍如何使用HttpClient操作HFS (HTTP File Server),为自己留个纪录也希望能帮助到有需要的开发人员.关于HTTP File Server的介绍.安装.设定,可 ...

  4. JVM知识(上)

    目录 什么是JVM? JVM的生命周期 JVM的体系结构 JVM的数据类型 java虚拟机被称为"虚拟",因为它是一个抽象的计算机定义的规范.要运行一个Java程序,需要一个抽象的 ...

  5. Selenium2+python自动化-文件上传

    前言 文件上传是web页面上很常见的一个功能,自动化成功中操作起来却不是那么简单. 一般分两个场景:一种是input标签,这种可以用selenium提供的send_keys()方法轻松解决:另外一种非 ...

  6. 解决Sublime Text 3中文显示乱码(tab中文方块)问题

    博客分类:  Sublime   一.文本出现中文乱码问题 1.打开Sublime Text 3,按Ctrl+-打开控制行,复制粘贴以下python代码,然后回车运行. 2. 复制并粘贴如下代码: P ...

  7. 简析Monte Carlo与TD算法的相关问题

    Monte Carlo算法是否能够做到一步更新,即在线学习? 答案显然是不能,如果可以的话,TD算法还有何存在的意义?MC算法必须要等到episode结束后才可以进行值估计的主要原因在于对Return ...

  8. 支持向量机SVM 初识

    虽然已经学习了神经网络和深度学习并在几个项目之中加以运用了,但在斯坦福公开课上听吴恩达老师说他(在当时)更喜欢使用SVM,而很少使用神经网络来解决问题,因此来学习一下SVM的种种. 先解释一些概念吧: ...

  9. jQuery 判断浏览器

    jQuery 浏览器判断,jQuery提供了一个 jQuery.browser 方法 来判断浏览器 可用值: safari   opera   msie   mozilla 例如:if($.brows ...

  10. Markdown分级语法手册

    目录 前言(可以不看) 基本语法(18) 1. 标题:# 2. 无序列表:- 3. 有序列表:1. 4. 斜体:* 5. 粗体:** 6. 加粗斜体:*** 7. 删除线:~~ 8. 分隔线:--- ...