• BZOJ4675: 点对游戏


    BZOJ4675: 点对游戏

    https://lydsy.com/JudgeOnline/problem.php?id=4675

    分析:

    • 对于一个人,如果选了m个点,答案显然是点对数量乘(inom{n-2}{m-2})(inom{n}{m})
    • 点分治统计点对数量即可。

    代码:

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    typedef double f2;
    #define N 100050
    int head[N],to[N<<1],nxt[N<<1],cnt,n;
    int m,lk[N],tot,a[N],la,b[N],lb,h[N];
    int dep[N],f[N],siz[N],root,used[N];
    f2 sum;
    inline void add(int u,int v) {
    	to[++cnt]=v; nxt[cnt]=head[u]; head[u]=cnt;
    }
    f2 work(int n,int m) {
    	return sum*m*(m-1)/(f2(n)*(n-1));
    }
    void get_root(int x,int y) {
    	int i;
    	siz[x]=1; f[x]=0;
    	for(i=head[x];i;i=nxt[i]) if(to[i]!=y&&!used[to[i]]) {
    		get_root(to[i],x);
    		siz[x]+=siz[to[i]];
    		f[x]=max(f[x],siz[to[i]]);
    	}
    	f[x]=max(f[x],tot-siz[x]);
    	if(f[x]<f[root]) root=x;
    }
    void get_dep(int x,int y) {
    	int i;
    	dep[x]=dep[y]+1;
    	a[++la]=x; b[++lb]=x;
    	for(i=1;i<=m;i++) {
    		if(lk[i]-dep[x]>=0) {
    			sum+=h[lk[i]-dep[x]];
    		}
    	}
    	for(i=head[x];i;i=nxt[i]) if(to[i]!=y&&!used[to[i]]) {
    		get_dep(to[i],x);
    	}
    }
    void solve(int x) {
    	used[x]=1;
    	int i,j;
    	la=lb=0;
    	a[++la]=0;
    	dep[x]=0;
    	h[0]=1;
    	for(i=head[x];i;i=nxt[i]) if(!used[to[i]]) {
    		lb=0;
    		get_dep(to[i],x);
    		for(j=1;j<=lb;j++) h[dep[b[j]]]++;
    	}
    	for(i=1;i<=la;i++) h[dep[a[i]]]=0;
    	for(i=head[x];i;i=nxt[i]) if(!used[to[i]]) {
    		tot=siz[to[i]]; root=0;
    		get_root(to[i],0);
    		solve(root);
    	}
    }
    int main() {
    	// freopen("game.in","r",stdin);
    	// freopen("game.out","w",stdout);
    	scanf("%d%d",&n,&m);
    	int i;
    	for(i=1;i<=m;i++) scanf("%d",&lk[i]);
    	int x,y;
    	for(i=1;i<n;i++) {
    		scanf("%d%d",&x,&y);
    		add(x,y), add(y,x);
    	}
    	tot=n;
    	root=0; f[0]=1<<30;
    	get_root(1,0);
    	solve(root);
    	printf("%.2f
    %.2f
    %.2f
    ",work(n,n/3+(n%3>0)),work(n,n/3+(n%3>1)),work(n,n/3));
    }
    
    
  • 相关阅读:
    C++ 虚函数表解析
    C#编写简单的聊天程序
    c#事件与委托
    c#文本控件实现换行
    docker 详细安装及问题排查
    hadoop命令行
    Spark中的多线程并发处理
    CDH6.1.0离线安装——笔记
    linux 常用命令
    Rsync 恢复 libselinux.SO.1
  • 原文地址:https://www.cnblogs.com/suika/p/10051637.html
Copyright © 2020-2023  润新知