• [CSP-S模拟测试]:randomwalking(DP)


    题目传送门(内部题59)


    输入格式

    第一行一个数$n$表示点数。
    第二行$n$个数$A_i$。
    接下来$n−1$行,每行两个数$u,v$表示$u$和$v$有边直接相连。


    输出格式

    一个数表示最小花费的起点。


    样例

    样例输入:

    5
    2 2 1 2 2
    1 2
    2 3
    3 4
    4 5

    样例输出:

    3


    数据范围与提示

    对于$10\%$的数据,保证$nleqslant 50$。
    对于$30\%$的数据,保证$nleqslant 500$。
    对于$50\%$的数据,保证$nleqslant 5,000$。
    对于$70\%$的数据,保证$nleqslant 1 imes {10}^5$。
    对于$100\%$的数据,保证$nleqslant 1 imes {10}^6$,$A_i$在$[1,1 imes {10}^9]$内随机生成


    题解

    又是一道假的期望,还好我及时的看了出来……

    我们设$g[i]$表示点$i$的子树对其的贡献,设$f[i]$表示点$i$的非子树对其的贡献。

    显然子树贡献很好求,即为:

    $$g[u]=sum limits_{v}frac{g[v]}{son[u]}+a[u]$$

    现在考虑非子树的,即为:

    $$f[u]=frac{(g[fa]+(g[fa]-a[fa]) imes son[u]-g[u])}{son[fa]}+a[fa]$$

    那么,每个点的答案即为:

    $$frac{(f[u]+(g[u]-a[u]) imes son[i])}{(son[i]+1)}+a[i]$$

    题目稍卡常(考试的时候把常数写的稍大,被卡掉了$10$分……)

    时间复杂度:$Theta(n)$。

    期望得分:$100$分。

    实际得分:$100$分。


    代码时刻

    #include<bits/stdc++.h>
    using namespace std;
    struct rec{int nxt,to;}e[2000001];
    int head[1000001],cnt;
    int n;
    double a[1000001];
    bool vis[1000001];
    double du[1000001];
    double dp[2][1000001];
    pair<int,double> ans;
    void add(int x,int y)
    {
    	e[++cnt].nxt=head[x];
    	e[cnt].to=y;
    	head[x]=cnt;
    }
    void dfs(int x)
    {
    	vis[x]=1;
    	dp[0][x]=a[x];
    	for(int i=head[x];i;i=e[i].nxt)
    		if(!vis[e[i].to])
    		{
    			dfs(e[i].to);
    			dp[0][x]+=dp[0][e[i].to]/du[x];
    		}
    }
    void DP(int x,int fa)
    {
    	dp[1][x]=(dp[1][fa]+(dp[0][fa]-a[fa])*du[fa]-dp[0][x])/du[fa]+a[fa];
    	double flag=(dp[1][x]+(dp[0][x]-a[x])*du[x])/(du[x]+1)+a[x];
    	if(fabs(flag-ans.second)<1e-8)ans.first=min(x,ans.first);
    	if(ans.second-flag>1e-8)ans=make_pair(x,flag);
    	for(int i=head[x];i;i=e[i].nxt)
    		if(e[i].to!=fa)DP(e[i].to,x);
    }
    int main()
    {
    	scanf("%d",&n);
    	for(int i=1;i<=n;i++)
    	{
    		scanf("%lf",&a[i]);
    		du[i]=-1;
    	}
    	du[1]=0;
    	for(int i=1;i<n;i++)
    	{
    		int x,y;
    		scanf("%d%d",&x,&y);
    		add(x,y);add(y,x);
    		du[x]++;du[y]++;
    	}
    	dfs(1);
    	ans=make_pair(1,dp[0][1]);
    	for(int i=head[1];i;i=e[i].nxt)
    		DP(e[i].to,1);
    	printf("%d",ans.first);
    	return 0;
    }
    

    rp++

  • 相关阅读:
    [Swift]LeetCode472. 连接词 | Concatenated Words
    [Swift]LeetCode470. 用 Rand7() 实现 Rand10() | Implement Rand10() Using Rand7()
    [Swift通天遁地]七、数据与安全-(19)使用Swift实现原生的SHA1加密
    [Swift通天遁地]七、数据与安全-(18)使用Swift实现原生的MD5加密
    [Swift通天遁地]七、数据与安全-(17)使用Swift实现原生的3DES加密和解密
    poj 1265 Area(pick 定理)
    Visual C++文件后缀名释义
    Linux 设备文件的创建和mdev
    37、ifconfig命令
    iOS开发- 生成/解析.vcf文件
  • 原文地址:https://www.cnblogs.com/wzc521/p/11593380.html
Copyright © 2020-2023  润新知