• 浙大集训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);
    }
    
  • 相关阅读:
    java程序打包成jar 配置文件信息路径
    django 认证系统
    django 表单验证和字段验证
    python 面向对象编程
    Python new() 方法
    Django 分页 以及自定义分页
    django 自己编写admin
    Django CRM客户关系管理系统
    Django model中的 class Meta 详解
    Django CRM系统
  • 原文地址:https://www.cnblogs.com/zhanglichen/p/15548810.html
Copyright © 2020-2023  润新知