• 洛谷 U141397 !


    洛谷 U141397 !

    洛谷传送门

    题目背景

    终于来到了最后一个电脑。你暗自嘲讽$$JZW$$最后一题想不出来名字只能用感叹号,心想下一套模拟赛要不要叫CXZL,走向了最后一台电脑。·

    题目描述

    你终于看见了被抓起来的$$JZW$$。看到了身为多项式之一的$$JZW$$的你十分喜悦,并和他一起合唱了《牵丝戏》和《九张机》,而要想解救他,你需要切掉这最后一道题。

    在你的面前是一颗无根树,树上每个节点都有一个权值。我们定义一个路径的权值为:该路径上所有节点权值的乘积除以路径上的节点数。

    例如,一条路径上包含两个权值分别为$$3,7$$,则该路径的权值为5

    现在,你需要计算出这棵树上权值最小的路径的权值,才能救出$$JZW$$。

    输入格式

    从文件fxxk.infxx**k.i**n中读入数据。

    第一行一个整数$$N$$,表示树共有$$N$$个节点

    接下来$$N-1$$行,每行两个整数$$a_i,b_i$$,表示编号为$$a_i,b_i$$的两个节点有一条无向边连接

    接下来$$N$$行,每行一个整数$$w_i$$,表示该节点$$i$$的权值

    输出格式

    输出到文件fxxk.outfxx**k.out中。

    一行,一个既约分数,形如p/q,如3/1


    题解:

    2020.11.23模拟赛T4 25分场

    觉得可以用点分治做。但是考场上一直没写出来。如果觉得点分治做法可行的小伙伴可以私信或留言联系我。咱俩一起研究。

    在考场上发现一个性质:1越多贡献越多。而且,除了1之外,再往里加任何数都不优。

    于是树形DP求了个最长的1链。最后假了,挂了好多分。

    问题出在哪呢?

    原来,2也是可以被放进这条链的。可以这样去想:现在有两条最长1链(分开的),只需要中间的一个2就可以把它们沟通起来。这样的答案有可能更优秀。

    于是我们就可以用(f[i],g[i])分别统计以i为根的子树中,以i为一端且魔力值为1的最大长度、魔力值为2的最大长度。

    当然,根据之前的思路,我们为了统计这些信息,还需要统计最大值、次大值。

    具体的在代码中实现:

    #include<cstdio>
    using namespace std;
    const int maxn=1e6+6;
    struct Node
    {
    	int next;
    	int to;
    }edge[maxn<<1];
    int head[maxn],cnt;
    void add(int u,int v)
    {
    	edge[cnt].next=head[u];
    	edge[cnt].to=v;
    	head[u]=cnt++;
    }
    int mag[maxn];
    int f[maxn],g[maxn];
    int p=1e9,q=1,mn=1e9;
    void update(int x,int y)
    {
    	if(p*y>q*x)
    		p=x,q=y;
    	return;
    }
    void dfs(int x,int fa)
    {
    	int u1=0,u2=0,v1=0,v2=0;
    	for(int i=head[x];~i;i=edge[i].next)
    	{
    		int t=edge[i].to;
    		if(t!=fa)
    		{
    			dfs(t,x);
    			if(f[t]>f[u1]){
    				u2=u1,u1=t;
    			}
    			else if(f[t]>f[u2]){
    				u2=t;
    			}
    			if(g[t]>g[v1]){
    				v2=v1,v1=t;
    			}
    			else if(g[t]>g[v2]){
    				v2=t;
    			}
    		}
    	}
    	if(mag[x]==1)
    	{
    		f[x]=f[u1]+1;
    		update(1,f[u1]+f[u2]+1);
    		if(v1!=0)
    		{
    			g[x]=g[v1]+1;
    			if(u1!=v1)
    				update(2,f[u1]+g[v1]+1);
    			else
    			{
    				update(2,f[u2]+g[v1]+1);
    				if(v2!=0)
    					update(2,f[u1]+g[v2]+1);
    			}
    		}
    	}
    	else if(mag[x]==2)
    	{
    		g[x]=f[u1]+1;
    		update(2,f[u1]+f[u2]+1);
    	}
    }
    int main()
    {
    	int n;
    	scanf("%d",&n);
    	for(int i=1;i<=n;++i)
    		head[i]=-1;
    	for(int i=1;i<n;++i)
    	{
    		int u,v;
    		scanf("%d%d",&u,&v);
    		add(u,v);
    		add(v,u);
    	}
    	for(int i=1;i<=n;++i)
    	{
    		scanf("%d",mag+i);
    		if(mag[i]<mn)
    			mn=mag[i];
    	}
    	if(mn>1)
    	{
    		printf("%d/1",mn);
    		return 0;
    	}
    	dfs(1,0);
    	printf("%d/%d",p,q);
    	return 0;
    }
    
  • 相关阅读:
    UOS怎么设置定时关机
    UOS如何修改源地址
    UOS如何进行全文搜索
    UOS如何查看硬盘序列号
    UOS如何修改右下角水印
    UOS怎么创建网页快捷方式
    应用商店安装软件提示uos-browser-stable错误,解决办法
    IHttpClientFactory Form 提交参数
    将.nuget文件夹移到其他盘
    windows docker 提示 bind: An attempt was made to access a socket
  • 原文地址:https://www.cnblogs.com/fusiwei/p/14026853.html
Copyright © 2020-2023  润新知