【题解】[COCI2016-2017#1] Mag

在这里插入图片描述

solution:

先抛出结论:

  1. 若不存在魔力值为 1 1 1 的节点,则魔力值最小的路径即为魔力值最小的节点。

  2. 若存在魔力值为 1 1 1 的节点,那么要么全部由 1 1 1构成,要么由 1 1 1 2 2 2和若干 1 1 1构成。

证明:
假设有一条最长的魔力值路径,可分为三种情况:
3. 没有为1的路径,那么显然不如 1 t \frac{1}{t} t1,其中 t t t是最小值
4. 有1段全为1的路径,假设长度为 t t t,其余部分乘积为 q q q,个数为 s s s,有不等式:
1 t < q t + s \frac{1}{t}<\frac{q}{t+s} t1<t+sq
因为 q > s , t > = 1 q>s,t>=1 q>s,t>=1,所以 t q > = t + s tq>=t+s tq>=t+s,显然得证
5. 有两段以上全为1的路径,考虑连接这两个部分的路径,设乘积为 q q q,假如 q > 2 q>2 q>2,其实不如选两段中较大的全为1的部分,因为分母的增量比原分母小,而分子的增量大于原分子,所以会更大,不会成为答案。当且仅当中间乘积为2即只有一个2时可能成为答案。
得证。

后记:
然后就没什么好说的了吧。。。

这道题告诉我们什么呢,分子是乘积,而分母的增量只有1,所以分子选大于1的数总是亏的。

但是这道题的结论有点违背常理可能是我太菜了,总之如果你的数学功底不好,光凭直觉还是不好想的。

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e6+5;
inline int read()
{
	int X=0; bool flag=1; char ch=getchar();
	while(ch<'0'||ch>'9') {if(ch=='-') flag=0; ch=getchar();}
	while(ch>='0'&&ch<='9') {X=(X<<1)+(X<<3)+ch-'0'; ch=getchar();}
	if(flag) return X;
	return ~(X-1);
}
int head[N*2],nxt[N*2],to[N*2],cnt;
int n,p,q,val[N],f[N],g[N];
void add(int x,int y) {
	to[++cnt]=y,nxt[cnt]=head[x],head[x]=cnt;
}
int gcd(int x,int y) {
	if(y==0) return x;
	return gcd(y,x%y);
}
void write(int x,int y) {
	int t=gcd(x,y);
	x/=t,y/=t;
	printf("%lld/%lld",x,y);
}
void change(int x,int y) {
	if(p==0&&q==0) p=x,q=y;
	else if(1.0*x/y<1.0*p/q) p=x,q=y;
}
void dfs(int x,int fath) {
	f[x]=g[x]=0;
	if(val[x]==1) f[x]=1;
	if(val[x]==2) g[x]=1;
	for(int i=head[x];i;i=nxt[i]) {
		int y=to[i];
		if(y==fath) continue;
		dfs(y,x);
		if(val[x]==1) change(1,f[y]+f[x]),change(2,g[y]+f[x]),change(2,g[x]+f[y]),f[x]=max(f[x],f[y]+1),g[x]=max(g[x],g[y]+1);
		else if(val[x]==2) change(2,g[x]+f[y]),g[x]=max(g[x],f[y]+1);
	}
}
signed main() {
    n=read();
    for(int i=1;i<n;i++) {
    	int x=read(),y=read();
    	add(x,y); add(y,x);
	}
	for(int i=1;i<=n;i++) val[i]=read();
	int flag=0,Min=0x3f3f3f3f;
	for(int i=1;i<=n;i++) 
	    if(val[i]==1) flag=1;
	    else Min=min(Min,val[i]);
	if(!flag) {
		printf("%lld/1",Min);
		return 0;
	}
	dfs(1,0);
	write(p,q);
}

顺便说一下:最近做了做 G S S GSS GSS系列,发现数据结构的题还是看功底,知道了思路就极其简单。

posted @ 2022-08-16 22:48  仰望星空的蚂蚁  阅读(17)  评论(0)    收藏  举报  来源