cf 512D - Fox And Travelling
题目大意
给定一颗\(n\le 100\)个点的图,可以进行随机游走,求游走\(k=0...n\)个点的方案数
游走的规则是:每次只能访问一个度数\(\le 1\)的点,并将其删除
分析
看完傻眼
问题1:随便顺序
问题2:稍微分析一下,发现环内的点不能选,甚至两个环的路径上的点都不能选
做法
对于问题2:并不需要缩点加奇怪处理找到不能选的点,只需要topu即可
可以发现,不可选集合会将联通快分成若干棵树,且不存在一棵树被不可选集合夹在中间的情况(这样的话这棵树就不可选,矛盾),于是划分出来的树一定所有节点的可选
整道题中,树有两类
1:有根树,即树根与一个不可选点相连,这时必须选完树中所有点才能选树根
2:无根树,即该联通快内不存在不可选点,此时哪个节点最后选择都可以
对于问题1:依然是树形背包dp
f[i][j]表示\(i\)子树中,选了\(j\)个点的方案数
dp合并的时候乘上组合数就好了
还是老问题:
\]
对于有根树是这样
那么对于无根树呢
我们枚举哪个节点最后删除,即对于树上每个点作为根求一次,dp值对应位加起来
此时对于\(n\)个点删除了\(i\)个点的情况,\(n-i\)个点作为根的时候都统计到了它,除一下
特别的,对于\(n\)个点删除了\(n\)个点的情况,不用除(也不能除n-n=0),因为这样既没有算重,也没有算漏,每个点最后删除的情况都枚举了,恰好就是所有情况
姿势
以后背包dp转移都可以写结构体,方便快捷
for循环边界思考过程:
枚举\(i+j=k\)的\(k\),再枚举\(i\)
满足不等式\(0\le i\le n\),\(0\le k-i \le m\)
以及组合数注意C(x,y)时特判x<y否则越界
solution
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cctype>
#include <cmath>
#include <algorithm>
#include <vector>
using namespace std;
const int M=107;
const int N=1e4+7;
const int Q=1e9+9;
typedef long long LL;
inline int pls(int x,int y){return ((LL)x+y)%Q;}
inline int mns(int x,int y){return pls(x,Q-y);}
inline int mul(int x,int y){return 1LL*x*y%Q;}
inline int ri(){
int x=0;bool f=1;char c=getchar();
for(;!isdigit(c);c=getchar()) if(c=='-') f=0;
for(;isdigit(c);c=getchar()) x=x*10+c-48;
return f?x:-x;
}
int n,m;
int inv[M],fac[M],ifac[M];
int vis[M],ok[M],deg[M];
vector<int>pt;
inline int C(int x,int y){return (x>=y) ? mul(fac[x],mul(ifac[y],ifac[x-y])) : 0;}
void init(){
int i;
for(inv[1]=1,i=2;i<=n;i++) inv[i]=mul(inv[Q%i],Q-Q/i);
for(fac[0]=1,i=1;i<=n;i++) fac[i]=mul(fac[i-1],i);
for(ifac[0]=1,i=1;i<=n;i++) ifac[i]=mul(ifac[i-1],inv[i]);
}
struct vec{
int g[M],te;
struct edge{
int y,nxt;
edge(int _y=0,int _nxt=0){y=_y,nxt=_nxt;}
}e[N<<1];
vec(){memset(g,0,sizeof(g));te=1;}
inline void push(int x,int y){e[++te]=edge(y,g[x]);g[x]=te;}
inline void push2(int x,int y){push(x,y);push(y,x);}
inline int& operator () (int x){return g[x];}
inline edge& operator [] (int x){return e[x];}
}e;
struct node{
int f[M],n;
node(){n=0;memset(f,0,sizeof f);}
void clear(){memset(f,0,sizeof f);n=0;}
inline int& operator [] (int x){return f[x];}
node operator *=(node &y){
int i,j,tp;
for(i=n+y.n;i>=0;i--){
for(tp=0,j=max(i-n,0);j<=min(i,y.n);j++)
tp=pls( tp, mul(C(i,j),mul(y[j],f[i-j])) );
f[i]=tp;
}
n+=y.n;
}
node operator +=(node &y){
int i;
for(i=0;i<=y.n;i++) f[i]=pls(f[i],y[i]);
n=max(n,y.n);
}
}ans,sum,f[M];
void topu(){
int i,h=0,t=0,x,p,y;
static int q[M];
for(i=1;i<=n;i++) if(deg[i]<=1) q[++t]=i;
while(h!=t){
x=q[++h];
ok[x]=1;
for(p=e(x);p;p=e[p].nxt){
y=e[p].y;
if(!ok[y]&&(--deg[y])<=1) q[++t]=y;
}
}
}
void dfs(int x,int fa){
vis[x]=1;
f[x].clear(); f[x][0]=1;
int p,y;
for(p=e(x);p;p=e[p].nxt)
if((y=e[p].y)!=fa){
dfs(y,x);
f[x]*=f[y];
}
f[x].n++;
f[x][f[x].n]=f[x][f[x].n-1];
}
void getpt(int x,int fa){
pt.push_back(x);
for(int p=e(x);p;p=e[p].nxt) if(e[p].y!=fa) getpt(e[p].y,x);
}
void gao(int x,int fa){
if(fa!=0){
dfs(x,fa);
ans*=f[x];
}
else{
int i,num;
pt.clear(); getpt(x,0); sum.clear();
for(i=0;i<pt.size();i++){
dfs(pt[i],0);
sum+=f[pt[i]];
}
for(i=0;i<pt.size();i++) sum[i]=mul(sum[i],inv[pt.size()-i]);
ans*=sum;
}
}
void solve(){
int i,x,y;
ans[0]=1;
for(i=1;i<=m;i++){
x=e[i<<1].y;
y=e[i<<1^1].y;
if(ok[x]!=ok[y])
ok[x] ? gao(x,y) : gao(y,x);
}
for(i=1;i<=n;i++)
if(ok[i]&&!vis[i]) gao(i,0);
}
int main(){
int i,x,y;
n=ri(),m=ri();
for(i=1;i<=m;i++){
x=ri(),y=ri();
deg[x]++,deg[y]++;
e.push2(x,y);
}
init();
topu();
solve();
for(i=0;i<=n;i++) printf("%d\n",ans.f[i]);
return 0;
}
cf 512D - Fox And Travelling的更多相关文章
- Codeforces 512D - Fox And Travelling(树上背包)
题面传送门 题意: 给出一张无向图,每次你可以选择一个度数 \(\leq 1\) 的点并将其删除. 问对于 \(k=0,1,2,\dots,n\),有多少个删除 \(k\) 个点的序列,答案模 \(1 ...
- CF 371B Fox Dividing Cheese[数论]
B. Fox Dividing Cheese time limit per test 1 second memory limit per test 256 megabytes input standa ...
- CF 510b Fox And Two Dots
Fox Ciel is playing a mobile puzzle game called "Two Dots". The basic levels are played on ...
- [CF #290-C] Fox And Names (拓扑排序)
题目链接:http://codeforces.com/contest/510/problem/C 题目大意:构造一个字母表,使得按照你的字母表能够满足输入的是按照字典序排下来. 递归建图:竖着切下来, ...
- cf E. Fox and Card Game
http://codeforces.com/contest/389/problem/E 题意:给你n个序列,然后两个人x,y,两个人玩游戏,x从序列的前面取,y从序列的后面取,两个人都想自己得到的数的 ...
- cf C. Fox and Box Accumulation
题意:输入一个n,然后输入n个数,问你可以划分多少个序列,序列为:其中一个数为c,在它的前面最多可以有c个数. 思路:先排序,然后对于每一个数逐步的找没有被用过的数,且这个数可以符合条件,然后如果没有 ...
- cf B. Fox Dividing Cheese
http://codeforces.com/contest/371/problem/B #include <cstdio> #include <iostream> #inclu ...
- IOI2020 国家集训队作业 泛做
题号 题目名称 rating 算法 完成情况 CF504E Misha and LCP on Tree CF505E Mr.Kitayuta vs. Bamboos CF506E Mr.Kitayut ...
- CF Fox And Names (拓扑排序)
Fox And Names time limit per test 2 seconds memory limit per test 256 megabytes input standard input ...
随机推荐
- 快速下载jar包
1, http://www.mvnrepository.com 2,可以从spring官网上下载,如果是mvn的话可以通过上面的网址下载
- C/C++程序基础 (六)面向对象
类的特性 抽象.封装.继承.多态.重载 class 和 struct 区别 C中struct仅仅可以包含数据成员,不可以有成员函数,属于复杂数据结构. C++ 中struct成员访问权限默认为publ ...
- (82)zabbix如何选择适合的监控类型
zabbix提供十几种监控类型,包括:Zabbix agent, Simple checks, SNMP, Zabbix internal, IPMI, JMX monitoring等等,那我们应该如 ...
- 十八、MySQL 排序
MySQL 排序 我们知道从 MySQL 表中使用 SQL SELECT 语句来读取数据. 如果我们需要对读取的数据进行排序,我们就可以使用 MySQL 的 ORDER BY 子句来设定你想按哪个字段 ...
- python笔记-for循环的方法
#!/usr/bin/env python #-*- coding:utf-8 -*- ''' for 语句 格式: for 变量名 in 集合: 语句 逻辑:按顺序取"集合"中的 ...
- python笔记-list列表的方法
#!usr/bin/python # -*- coding: utf-8 -*- # 存储5个人的年龄,求他们的平均年龄 age1 = 18 age2 = 15 age3 = 38 age4 = 20 ...
- java util - 中文、繁体转成拼音工具pinyin4j
需要 pinyin4j-2.5.0.jar 包 代码例子 package cn.java.pinyin4j; import net.sourceforge.pinyin4j.PinyinHelper; ...
- ubuntu crontab设置定时任务
ubuntu 设置定时任务 crontab -l #查看详情crontab -e #设置定时任务 * * * * * command 分 时 日 月 周 命令 第1列表示分钟1-59 每分钟用* ...
- 单片机入门学习笔记6:新唐单片机N76E003
学习新唐单片机是从2018年3月开始的,之前一点也不懂这一块单片机,之后脉络变的越来越清晰. 由于N76E003档次太低,新塘科技官方的管脚配置,芯片选型……都没有这一块芯片,资料唯独只有:芯片的数据 ...
- B1020 月饼(25 分)
B1020 月饼(25 分) 月饼是中国人在中秋佳节时吃的一种传统食品,不同地区有许多不同风味的月饼.现给定所有种类月饼的库存量.总售价.以及市场的最大需求量,请你计算可以获得的最大收益是多少. 注意 ...