浙大集训day9:E.Lemon Tree

浙大集训day9:E.Lemon Tree

小A昨晚做了一个梦。

他坐在柠檬树下,成为了一名伟大的物理学家。

柠檬树是惊人的,他的每条边都有一个权重\(c\),但是\(c\)只能是\(0\)\(1\)

他忘记了每条边的相应权重,但是他想起了一些特征:

树有\(m\)个特征,每个特征\((a,b,c)\)表示:

从节点\(a\)到节点\(b\),模2的路径是\(c\)

\(A\)想知道不同柠檬树的数量。

两颗柠檬树不同,当且仅当它们至少有两个重量不同的边。

做法:

玄学做法,我也忘了咋做了。

#include<bits/stdc++.h>
using namespace std;
const int maxn=3e5+100;
const int mod=998244353;
int n,m;
vector<int> g[maxn];
vector<pair<int,int> > gg[maxn];
struct node {
	int u,v,w;
}a[maxn];
int father[maxn];
int findfather (int x) {
	int a=x;
	while (x!=father[x]) x=father[x];
	while (a!=father[a]) {
		int z=a;
		a=father[a];
		father[z]=x;
	}
	return x;
}
int fa[30][maxn];
int h[maxn];
int d[maxn];
int vis[maxn];
void dfs (int x,int u) {
	vis[x]=1;
	fa[0][x]=u;
	for (int i=1;(1<<i)<=h[x];i++) {
		fa[i][x]=fa[i-1][fa[i-1][x]];
	}
	for (pair<int,int> it:gg[x]) {
		int y=it.first;
		if (y==fa[0][x]) continue;
		h[y]=h[x]+1;
		d[y]=d[x]+it.second;
		dfs(y,x);
	}
}
int lca (int x,int y) {
    if (h[x]>h[y]) swap(x,y);
    for (int i=20;i>=0;i--)
        if (h[x]<=h[y]-(1<<i)) y=fa[i][y];
    if (x==y) return x;
    for (int i=20;i>=0;i--) 
        if (fa[i][x]!=fa[i][y]) {
            x=fa[i][x];
            y=fa[i][y];
        } 
    return fa[0][x];
}
int getDis (int x,int y) {
    return d[x]+d[y];
}
map<pair<int,int> ,int> mp;
typedef long long ll;
ll qpow (ll a,ll b) {
	ll ans=1,base=a;
	while (b) {
		if (b&1) {
			ans=ans*base%mod;
		} 
		base=base*base%mod;
		b>>=1;
	}
	return ans;
}
inline int read()
{
	int x=0,f=1;char c=getchar();
	while(c<'0'||c>'9') {if(c=='-') f=-1;c=getchar();}
	while (c>='0'&&c<='9') x=(x<<3)+(x<<1)+(c^48),c=getchar();
	return x*f;
}
int is[maxn];
int main () {
	n=read();
	m=read();
	if (n==1) {
		while (m--) {
			int u,v,w;
			//scanf("%d%d%d",&u,&v,&w);
			u=read();
			v=read();
			w=read();
			if (u==1&&v==1&&w==0) continue;
			printf("0\n");
			return 0;
		}
		printf("1\n");
		return 0;
	}
	for (int i=1;i<n;i++) {
		int x,y;
		//scanf("%d%d",&x,&y);
		x=read();
		y=read();
		g[x].push_back(y);
		g[y].push_back(x);
	}
	for (int i=1;i<=n;i++) father[i]=i;
	for (int i=1;i<=m;i++) {
		//scanf("%d%d%d",&a[i].u,&a[i].v,&a[i].w);
		a[i].u=read();
		a[i].v=read();
		a[i].w=read();
		int uu=findfather(a[i].u);
		int vv=findfather(a[i].v);
		if (uu==vv) continue;
		is[i]=1;
		father[uu]=vv;
		gg[a[i].u].push_back(make_pair(a[i].v,a[i].w));
		gg[a[i].v].push_back(make_pair(a[i].u,a[i].w));
	}
	for (int i=1;i<=n;i++) {
		if (!vis[i]) dfs(i,i);
	}
	for (int i=1;i<=m;i++) {
		if (a[i].w>=2) return printf("0\n"),0;
		if (findfather(a[i].u)!=findfather(a[i].v)) continue;
		if (getDis(a[i].u,a[i].v)%2!=a[i].w) {
			printf("0\n");
			return 0;
		}
	}
	long long ans=1;
	for (int i=1;i<n;i++) ans*=2,ans%=mod;
	ll x=qpow(2,mod-2);
	for (int i=1;i<=m;i++) {
		if (mp[make_pair(a[i].u,a[i].v)]) continue;
		if (!is[i]) continue;
		mp[make_pair(a[i].u,a[i].v)]++;
		mp[make_pair(a[i].v,a[i].u)]++;
		if (a[i].u==a[i].v) continue;
		ans*=x;
		ans%=mod;
	}
	printf("%lld\n",ans);
}
原文地址:https://www.cnblogs.com/zhanglichen/p/15548810.html