浙大集训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);
}