【刷题】【省选】ZJOI2017_仙人掌_LOJ2250/Luogu3687_圆方树/dp计数/树形dp

时间:2020-06-07 16:58:41   收藏:0   阅读:40

链接

LOJ2250
Luogu3687

题解

代码

#include<bits/stdc++.h>
#define LL long long
#define MAXN 1000000
#define MAXM 1000000
#define MOD 998244353
using namespace std;
template<typename T>void Read(T &cn)
{
	char c;int sig = 1;
	while(!isdigit(c = getchar()))if(c == ‘-‘)sig = -1; cn = c-48;
	while(isdigit(c = getchar()))cn = cn*10+c-48; cn*=sig;
}
template<typename T>void Write(T cn)
{
	if(cn < 0) {putchar(‘-‘); cn = 0-cn; }
	int wei = 0; T cm = 0; int cx = cn%10; cn/=10;
	while(cn)cm = cm*10+cn%10,cn/=10,wei++;
	while(wei--)putchar(cm%10+48),cm/=10;
	putchar(cx+48);
}
template<typename T>void Min(T &cn, T cm) {cn = cn < cm ? cn : cm; }
struct Tree{
	struct qwe{
		int a,b,ne;
		void mk(int cn, int cm, int cx) {a = cn; b = cm; ne = cx; }
	};
	qwe a[MAXM+1];
	int alen;
	int head[MAXN+1];
	void build(int cn) {alen = 0; for(int i = 1;i<=cn;i++) head[i] = 0; }
	void lian(int cn, int cm) {a[++alen].mk(cn,cm,head[cn]); head[cn] = alen; }
	void lian_d(int cn, int cm) {lian(cn, cm); lian(cm, cn); }
}T1, T2;
int n,m,t;
int dfn[MAXN+1], low[MAXN+1], zhan[MAXN+1], guo[MAXN+1], shi, zlen;
int vis[MAXN+1];
LL f[MAXN+1][2];
LL h[MAXN+1];
void yuchu(int cn) {h[0] = h[1] = 1; for(int i = 2;i<=cn;i++) h[i] = (h[i-1]+1ll*(i-1)*h[i-2])%MOD; }
int tarjan(int cn, int fa)
{
	guo[cn] = 0;
	dfn[cn] = low[cn] = ++shi;
	zhan[++zlen] = cn;
	for(int i = T1.head[cn];i;i = T1.a[i].ne)
	{
		int y = T1.a[i].b;
		if(y == fa) continue;
		if(dfn[y]) {
			Min(low[cn], dfn[y]);
			if(guo[cn] && guo[y] != cn) return -1;
			if(guo[y] != cn) guo[cn] = y;
		}
		else {
			int lin = zlen;
			int lin2 = tarjan(y, cn);
			Min(low[cn], low[y]);
			if(lin2 == -1) return -1;
			if(low[y] >= dfn[cn]) {
				if(lin2 != cn && lin2 != 0) return -1;
				if(zlen == lin+1) T2.lian_d(cn, zhan[zlen]);
				zlen = lin;
			}
			else {
				if(lin2 && guo[cn]) return -1;
				if(!guo[cn]) guo[cn] = lin2;
			}
		}
	}
	return guo[cn];
}
void dfs(int cn, int fa)
{
	vis[cn] = 1; 
	f[cn][0] = 1;
	int ge = 0;
	for(int i = T2.head[cn];i;i = T2.a[i].ne) 
	{
		int y = T2.a[i].b;
		if(y == fa) continue;
		dfs(y, cn);
		f[cn][0] = 1ll*f[cn][0]*(f[y][1] + f[y][0])%MOD;
		ge++;
	}
	f[cn][1] = f[cn][0] * h[ge-1]%MOD *ge%MOD;
	f[cn][0] = f[cn][0] * h[ge]%MOD;
}
void zuo()
{
	Read(n); Read(m);
	T1.build(n); T2.build(n);
	for(int i = 1;i<=m;i++) {int bx,by; Read(bx); Read(by); T1.lian_d(bx,by); }
	shi = zlen = 0; for(int i = 1;i<=n;i++) dfn[i] = low[i] = 0;
	if(tarjan(1, 0) == -1) {puts("0"); return; }
	LL ans = 1; for(int i = 1;i<=n;i++) vis[i] = 0;
	for(int i = 1;i<=n;i++) if(!vis[i]) dfs(i, 0), ans = ans*f[i][0]%MOD;
	Write(ans); puts("");
}
int main() {yuchu(MAXN); Read(t); while(t--) zuo(); return 0; }

原文:https://www.cnblogs.com/czyarl/p/13061106.html

评论(0
© 2014 bubuko.com 版权所有 - 联系我们:wmxa8@hotmail.com
打开技术之扣,分享程序人生!