zoukankan      html  css  js  c++  java
  • Codeforces Round #665 (Div. 2) D. Maximum Distributed Tree

    题意:给一棵树的边赋边权,要求边权积等于m(m以质因数分解形式给出),且边上1的个数尽量少,目的最大化两两点对路径和之和

    吕老板讲过,树上统计两两点对路径和,考虑每条边的贡献,对于一条边,它贡献的次数就是它两侧子树的大小之积,用dfs求出siz,贡献次数w就是siz*(n-siz)

    把w数组从大到小排序,如何安排m?

    m的质因数分解形式也从大到小排序,要求1最少,那就优先给每个w排上一个数,由排序不等式(或者直觉),大的配大的

    首先,考虑边数比m分解的数多的情况,那就尽量安排大的在前面,后面的补1

    再考虑边数比m分解数少的情况,想到两个情况,把从大到小安排后,把剩下的安排到最大;或者从小到大安排,再安排剩下的到最大

    考虑贡献次数(w_1)(w_2)的两条边,安排(a,b,c)三个数(顺序默认从大到小),结果就是(acw_1+bw_2)(abw_1+cw_2),显然第二个大,所以策略是最大的安排到最大的边,直到剩下的正好覆盖剩余的边

    呼之欲出

    #include<bits/stdc++.h>
    
    using namespace std;
    
    inline int rd(){
    	int ret=0,f=1;char c;
    	while(c=getchar(),!isdigit(c))f=c=='-'?-1:1;
    	while(isdigit(c))ret=ret*10+c-'0',c=getchar();
    	return ret*f;
    }
    #define pc putchar
    #define space() pc(' ')
    #define nextline() pc('
    ')
    void pot(int x){if(!x)return;pot(x/10);pc('0'+x%10);}
    void out(int x){if(!x)pc('0');if(x<0)pc('-'),x=-x;pot(x);}
    
    const int MOD = 1e9+7; 
    const int MAXN = 100005;
    
    struct Edge{
    	int next,to;	
    }e[MAXN<<1];
    int head[MAXN],ecnt;
    inline void add(int x,int y){
    	e[++ecnt].next = head[x];
    	e[ecnt].to = y;
    	head[x] = ecnt;	
    }
    
    typedef long long ll;
    
    int n,m;
    ll ps[MAXN],w[MAXN];
    
    int siz[MAXN];
    void dfs(int x,int pre){
    	siz[x]=1;
    	for(int i=head[x];i;i=e[i].next){
    		int v=e[i].to;
    		if(v==pre) continue;
    		dfs(v,x);
    		siz[x]+=siz[v];	
    	}
    }
    
    void solve(){
    	memset(siz,0,sizeof(siz));
    	memset(head,0,sizeof(head));
    	memset(ps,0,sizeof(ps));
    	ecnt=0;
    	//clear
    	n=rd();
    	int x,y;
    	for(int i=1;i<=n-1;i++){
    		x=rd();y=rd();
    		add(x,y);add(y,x);
    	}
    	m=rd();
    	for(int i=1;i<=m;i++){
    		ps[i]=rd();
    	}
    	sort(ps+1,ps+1+m);
    	reverse(ps+1,ps+1+m);
    	dfs(1,-1);
    	for(int i=1;i<=ecnt;i+=2){
    		int u=e[i].to;
    		int v=e[i+1].to;
    		ll mn=min(siz[u],siz[v]);
    		w[(i+1)>>1]=1ll*mn*(n-mn);
    		
    //		w[(i+1)>>1]=mn;	
    	}
    	sort(w+1,w+1+(n-1));
    	reverse(w+1,w+1+(n-1));
    //	cerr<<"DEBUG:";
    //	for(int i=1;i<=n-1;i++) cerr<<w[i]<<" ";
    //	cerr<<endl;
    	ll ans=0;
    	if((n-1)>=m){
    		for(int i=1;i<=n-1;i++){
    			int y=ps[i];
    			if(y==0) y=1;
    			ans+=(ll)(1ll*w[i]*y);
    			ans%=MOD;
    		}
    //		cerr<<"ANS:";
    		cout<<ans<<endl;
    		return;
    	}else{
    		ll tmp=1;
    		for(int i=1;i<=(m-n+2);i++){
    			tmp*=(ll)(1ll*ps[i]);
    			tmp%=MOD;
    		}
    		ans+=(ll)(1ll*tmp*w[1]);
    		ans%=MOD;
    		for(int i=2;i<=n-1;i++){
    			int j=i+m-n+1;
    			ans+=(ll)(1ll*w[i]*ps[j]);
    			ans%=MOD;	
    		}
    //		cerr<<"ANS:";
    		cout<<ans<<endl;
    		return;
    	}
    	
    }
    
    int main(){
    	int t=rd();
    	while(t--) solve();
    	return 0;
    }
    
    
  • 相关阅读:
    sqlserver2005系统表、视图研究2
    SQLServer2005新分页方法
    应该多了解一些工具
    关于SQLServer的小技巧
    EasyUI DataGrid使用Json加载不了数据
    js跨域及解决方案
    关于Master Page的css和js文件引用问题
    嵌套母版页
    SSMS获取存储过程中的返回值和output值
    静态构造函数
  • 原文地址:https://www.cnblogs.com/ghostcai/p/13549423.html
Copyright © 2011-2022 走看看