网站开发服务合同范本,wordpress中国优化,郑州seo线上推广技术,项目策划书八篇案例传送门 文章目录题意#xff1a;思路#xff1a;题意#xff1a;
给你一棵树#xff0c;求这棵树的边导出子图中独立集的数量和#xff0c;独立集大小可以为000。
思路#xff1a;
先考虑普通的独立集数量怎么求#xff0c;无非就是分情况讨论一下选根还是不选根思路题意
给你一棵树求这棵树的边导出子图中独立集的数量和独立集大小可以为000。
思路
先考虑普通的独立集数量怎么求无非就是分情况讨论一下选根还是不选根而这个题多了一个边导出子图的条件那么无非就是多了一个选择那就是切掉根与其儿子的边所以直接考虑类似的dpdpdp多加一个切边的操作就好啦。 定义f[i][j]f[i][j]f[i][j]表示到以iii为根的子树状态为jjj的时候的独立集个数。 f[i][0]f[i][0]f[i][0]表示iii可以选也可以不选并且iii与其父亲节点之间的边不选。 f[i][1]f[i][1]f[i][1]表示选iii这个点并且iii与其父亲之间有边。 f[i][2]f[i][2]f[i][2]表示不选iii这个点并且iii与其父亲之间有边。 这个题主要是难在状态的设计上我们设计出状态来转移就比较好想了。 (1)j1(1)j1(1)j1时由于选了iii这个点所以要不就断掉iii与他儿子的边要不就加上与他儿子的边并且不选他儿子。f[i][1]∏(f[j][0]f[j][2])f[i][1]\prod (f[j][0]f[j][2])f[i][1]∏(f[j][0]f[j][2]) (2)j2(2)j2(2)j2时由于没选iii这个点那么他与儿子之间的关系随意。f[i][2]∏(f[j][0]f[j][1]f[j][2])f[i][2]\prod (f[j][0]f[j][1]f[j][2])f[i][2]∏(f[j][0]f[j][1]f[j][2]) (3)j3(3)j3(3)j3时显然f[i][0]f[i][1]f[i][2]f[i][0]f[i][1]f[i][2]f[i][0]f[i][1]f[i][2]但是这样就行了吗要知道f[i][1]f[i][2]f[i][1]f[i][2]f[i][1]f[i][2]是包含了与iii的儿子之间的边都不选的情况我们现在与iii的父亲之间的边也不选了那么iii这个点不就被孤立了吗但是边导出子图是肯定不能有孤立的点的所以我们要减去∏f[j][0]\prod f[j][0]∏f[j][0]。f[i][0]f[i][1]f[i][2]−∏f[j][0]f[i][0]f[i][1]f[i][2]-\prod f[j][0]f[i][0]f[i][1]f[i][2]−∏f[j][0] 最终的答案即为f[1][0]−1f[1][0]-1f[1][0]−1因为不能选的边集为空集。
// Problem: F. Independent Set
// Contest: Codeforces - Codeforces Round #630 (Div. 2)
// URL: https://codeforces.com/contest/1332/problem/F
// Memory Limit: 512 MB
// Time Limit: 2000 ms
//
// Powered by CP Editor (https://cpeditor.org)//#pragma GCC optimize(Ofast,no-stack-protector,unroll-loops,fast-math)
//#pragma GCC target(sse,sse2,sse3,ssse3,sse4.1,sse4.2,avx,avx2,popcnt,tunenative)
//#pragma GCC optimize(2)
#includecstdio
#includeiostream
#includestring
#includecstring
#includemap
#includecmath
#includecctype
#includevector
#includeset
#includequeue
#includealgorithm
#includesstream
#includectime
#includecstdlib
#define X first
#define Y second
#define L (u1)
#define R (u1|1)
#define pb push_back
#define mk make_pair
#define Mid (tr[u].ltr[u].r1)
#define Len(u) (tr[u].r-tr[u].l1)
#define random(a,b) ((a)rand()%((b)-(a)1))
#define db puts(---)
using namespace std;//void rd_cre() { freopen(d://dp//data.txt,w,stdout); srand(time(NULL)); }
//void rd_ac() { freopen(d://dp//data.txt,r,stdin); freopen(d://dp//AC.txt,w,stdout); }
//void rd_wa() { freopen(d://dp//data.txt,r,stdin); freopen(d://dp//WA.txt,w,stdout); }typedef long long LL;
typedef unsigned long long ULL;
typedef pairint,int PII;const int N1000010,mod998244353,INF0x3f3f3f3f;
const double eps1e-6;int n;
vectorintv[N];
LL f[N][3];
// 0 选不选都行 但是与父亲之间没边
// 1 选这个点 但是与父亲之间有边
// 2 不选这个点 但是与父亲之间有边void dfs(int u,int fa) {LL fun1;for(auto x:v[u]) {if(xfa) continue;dfs(x,u);(f[u][1]*(f[x][0]f[x][2])%mod)%mod;(f[u][2]*(f[x][0]f[x][1]f[x][2])%mod)%mod;(fun*f[x][0])%mod;}f[u][0]((f[u][1]f[u][2]-fun)%modmod)%mod;//由于如果他的到叶子的边都不选的而且u选的话那么就是一个孤立的点了这是不允许的
}int main()
{
// ios::sync_with_stdio(false);
// cin.tie(0);scanf(%d,n);for(int i1;in-1;i) {int a,b; scanf(%d%d,a,b);v[a].pb(b); v[b].pb(a);}for(int i1;in;i) f[i][1]f[i][2]1;dfs(1,0);printf(%lld\n,((f[1][0]-1)%modmod)%mod);//减去空集的情况return 0;
}
/**/