• Edge Weight Assignment(树-异或-贪心)


    大意: 给定一棵无根树,要求你任意设置n-1条边的边权.

    使得任意叶子节点间边权的XOR值为0;
    此时,令f为所有边权数值不同的个数,求最小的f和最大的f.

    (color{Red}{--------------------我是华丽的分割线(●ˇ∀ˇ●)-----------------------})

    (看上去很难吧??)做起来也很难

    (color{Red}{Ⅰ.考虑最小})

    (那请你先想个简单的问题,考虑两个叶子节点f最小值的情况。很容易想到我在路上全挂满1对吧?)

    (但问题来了,如果两个叶子间的距离为奇数,就行不通了。这时候最小值怎么算呢?)

    (全放1肯定不行,少放1个1也不行,这样要抵消成0的话还是要放1.)

    (color{Purple}{那就少放两个1,让这连个数异或后可以抵消掉1,这样并不难})

    (color{Red}{Ⅱ.考虑最大})

    (这个似乎就很难了。但是一开始肯定希望把路上放满不同的数,这样肯定可以异或成0.)

    (为什么?回想一下异或的性质,我是不是可以这样放权值)

    (0000001,0000010,0000100,0001000......突然到最后,放一个11111111和前面全部抵消)

    (完美!!这样我们的答案就是 n-1 !! 不过用脚想也知道没这么简单。什么时候不满足呢?)

    (当叶子节点距离只有2的时候无法满足,2是XOR的特殊情况,想为0就必须放两个相同的。)

    #include <bits/stdc++.h>
    using namespace std;
    const int maxn=2e5+5;
    struct p{
    	int to,nxt;
    }d[maxn];int n,head[maxn],cnt=1;
    void add(int u,int v){
    	d[cnt].nxt=head[u],d[cnt].to=v,head[u]=cnt++;
    }
    int indug[maxn],deep[maxn],ji,ou,father[maxn];
    void dfs(int u,int fa)
    {
    	deep[u]=deep[fa]+1;
    	if(indug[u]==1)
    	{
    		if(deep[u]%2)	ji=1;
    		else	ou=1;
    		father[fa]++;
    		return;
    	}
    	for(int i=head[u];i;i=d[i].nxt)
    		if(d[i].to!=fa)	dfs(d[i].to,u);
    }
    int main()
    {
    	cin>>n;
    	for(int i=1;i<n;i++)
    	{
    		int l,r;
    		cin>>l>>r;
    		add(l,r);add(r,l);
    		indug[l]++,indug[r]++;
    	}
    	int root;
    	for(int i=1;i<=n;i++)
    	if(indug[i]!=1)	root=i;//随便找一个不是叶子的节点为根
    	dfs(root,root); 
    	if(ji&&ou)	cout<<3<<" ";
    	else	cout<<1<<" ";
    	int ans=n-1;
    	for(int i=1;i<=n;i++)
    		if(father[i])	ans=ans-father[i]+1;
    	cout<<ans;
    } 
    
  • 相关阅读:
    P1019 单词接龙
    P1219 八皇后
    Find a way
    P1056 排座椅
    P1067 多项式输出
    关于前缀和,A
    洛谷P1223
    洛谷P1803
    洛谷P1208
    常用方法 Excel转换为DataSet
  • 原文地址:https://www.cnblogs.com/iss-ue/p/12789533.html
Copyright © 2020-2023  润新知