zoukankan      html  css  js  c++  java
  • 题解 P7846 「dWoi R2」Arcade hall / 街机厅

    (quad)可以发现第一问和第二问并无关联,所以可以分开讨论。

    第一问

    (quad)显然是树形DP,可以从上向下DP,(f_i) 表示 (i) 号结点可能的方案数,(son_i)(i) 号结点的儿子数,设 (j) 为i的一个儿子,(val_{i,j})(i,j) 连边的关系((t))。

    (quad)可得:

    [ left{ egin{aligned} & f_{root}= R\ & f_j= & R-1(val_{i,j}=0)\ & f_j= & R(val_{i,j}=1)\ & f_j= & 1(val_{i,j}=2) end{aligned} ight. ]

    (quad)最终答案就是 (prodlimits_{i=1}^{n}f[i])

    第二问

    (quad)同样是树形DP,但是是从下向上传递答案,设 (g_{i,j})(i) 号结点取 (j) 时子树的最小值,R并不大,所以可以逐一枚举。(经测试,枚举到13即可)

    (quad)可得:(设 (p_{i,0})(g_{i,j})中的最小值, (p_{i,1}) 为次小值, (v)(i) 的一个儿子)

    [g_{i,j}=j ]

    [ left{ egin{aligned} & g_{i,j}+= p_{v,0} (val_{i,v}=0,p_{v,1}>=g_{v,j})\ & g_{i,j}+= p_{v,1} (val_{i,v}=0,p_{v,1}<g_{v,j})\ & g_{i,j}+= p_{v,0} (val_{i,v}=1)\ & g_{i,j}+= g_{v,j}(val_{i,v}=2) end{aligned} ight. ]

    (quad)最后的答案就是 (p_{root,0})

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<cstring>
    #include<cstdlib>
    #include<time.h>
    #define int long long
    #define re register int
    #define il inline
    using namespace std;
    il int read()
    {
      int x=0,f=1;char ch=getchar();
      while(!isdigit(ch)&&ch!='-')ch=getchar();
      if(ch=='-')f=-1,ch=getchar();
      while(isdigit(ch))x=(x<<1)+(x<<3)+ch-'0',ch=getchar();
      return x*f;
    }
    il void print(int x)
    {
      if(x<0)putchar('-'),x=-x;
      if(x/10)print(x/10);
      putchar(x%10+'0');
    }
    il int min(int x,int y){return x<y?x:y;}
    const int N=1e5+5,MOD=1e9+7,inf=0x3f3f3f3f;
    int n,R,p,rt,tot,ans=1,head[N],nxt[N<<1],val[N<<1],go[N<<1],f[N],g[N][15];
    il void Add(int x,int y,int z)
    {
    	nxt[++tot]=head[x];
    	head[x]=tot;go[tot]=y;val[tot]=z;
    }
    il void dfs(int x,int fa,int h)//g[i][0]表示最小值,g[i][14]表示次小值
    {
    	for(re i=1;i<=p;i++)g[x][i]=i;//初始的代价
    	if(h==1)f[x]=R;else if(h==2)f[x]=1;else f[x]=R-1;//第一问
    	for(re i=head[x],y;i,y=go[i];i=nxt[i])
    	if(y!=fa){
    		dfs(y,x,val[i]);
    		for(re j=1;j<=p;j++)
    		if(val[i]==1)g[x][j]+=g[y][0];
    		else if(val[i]==2)g[x][j]+=g[y][j];
    		else {
    			if(g[y][j]>=g[y][14])g[x][j]+=g[y][0];
    			else g[x][j]+=g[y][14];
    		}
    	}
    	g[x][0]=g[x][14]=inf;
    	for(re i=1;i<=p;i++)//更新最小值和次小值
    	{
    		if(g[x][i]<g[x][0])g[x][14]=g[x][0],g[x][0]=g[x][i];
    		else if(g[x][i]==g[x][0])g[x][14]=g[x][i];
    		else if(g[x][i]<g[x][14])g[x][14]=g[x][i];
    	}
    }
    signed main()
    {
    	n=read();R=read();srand(time(0));rt=rand()%n+1;p=min(R,13);//随机的根不容易被卡
    	for(re i=1,x,y,z;i<n;i++)x=read(),y=read(),z=read(),Add(x,y,z),Add(y,x,z);
    	dfs(rt,0,1);
    	for(re i=1;i<=n;i++)ans=(ans*f[i])%MOD;//记得要取模
    	print(ans);putchar(' ');if(ans==0){putchar('0');return 0;}
    	print(g[rt][0]);
    	return 0;
    }
    

    [ exttt{后记} ]

    (quad)一开始以为只填1或2就是最小值,然而只有30分,至今不知道为什么?

    (quad)这里有一组数据,有大佬可以解释吗?

  • 相关阅读:
    android 控件: xml 设置 Button 按下背景
    Hadoop: the definitive guide 第三版 拾遗 第四章
    二进制日志占满空间
    Unity3d学习笔记记录
    百度地图api---实现新建地图
    php简单浏览目录内容
    CRC校验的实现
    Android记录3--ExpandableListView使用+获取SIM卡状态信息
    Zookeeper Api(java)入门与应用(转)
    ZooKeeper程序员指南(转)
  • 原文地址:https://www.cnblogs.com/FarkasW/p/15463184.html
Copyright © 2011-2022 走看看