Mag

\(设l(x)表示长度,m(x)表示乘积\)


\(考虑没有1的情况\)

\(连接x,y两条链\)

\(设\)

\[\dfrac{m(x)}{l(x)}<\dfrac{m(y)}{l(y)} \]

\(则\)

\[\dfrac{m(x)}{m(y)}<\dfrac{l(x)}{l(y)} \]

\(若连接后优\)

\[\dfrac{m(x)m(y)}{l(x)+l(y)}<\dfrac{m(x)}{l(x)} \]

\[\dfrac{m(y)}{l(x)+l(y)}<\dfrac{1}{l(x)} \]

\[l(x)m(y)<l(x)+l(y) \]

\[(m(y)-1)<\dfrac{l(y)}{l(x)}<\dfrac{m(y)}{m(x)} \]

\[(m(x)m(y))-m(x)-m(y)+1<1 \]

\[(m(x)-1)(m(y)-1)<1 \]

\(m(x),m(y)>1显然不成立\)


\(考虑一条的链x\)

\((1)若x是M>1,两边有许多1\)

\(设M左边有l个1,右边有r个1,规定l\leq r(其实r>l等价)\)

\(若要选M\)

\[\dfrac{M}{l+r+1}<\dfrac{1}{r} \]

\[M<1+\dfrac{l+1}{r} \]

\(当且仅当l=r,M=2时,这样选最优\)

\((2)若x是M>1,N>1相连,中间与两边夹着许多1\)

\(设M左N右\)

\(设l为M左边1的个数,r为N右边1的个数,m为中间1的个数,k=max(l,m,r)\)

\(若要选该链\)

\[\dfrac{NM}{l+r+m+2}<\dfrac{1}{k} \]

\[NMk<l+r+m+2 \]

\[\because N\geq2,M\geq2 \]

\[\therefore l+r+m+2>NMk\geq4k \]

\(当且仅当l=r=m满足,即1-2-1-2-1,但1-2-1明显更优\)

\((3)若x是M>1,N>1相连,两边夹着许多1,中间没有\)

\(设M左N右\)

\(设l为M左边1的个数,r为N右边1的个数,k=max(l,r)\)

\(若要选该链\)

\[\dfrac{NM}{l+r+2}<\dfrac{1}{k} \]

\[\therefore l+r+2>NMk\geq4k \]

\(明显不成立\)

\(由(2)(3)可以推广到一般\)

\(结论:(1)无1选最小\)

\((2)有一选最长的1或1中夹着一个2\)


\(考虑实现\)

#include <bits/stdc++.h>
#pragma GCC optimize(2)
using namespace std;
template<typename ll=int>
class Frac
{
	private:
		ll abs(const ll& x)const{return x<0?-x:x;}
		ll gcd(const ll& x,const ll& y)const{return y?gcd(y,x%y):x;}
		Frac reduce()
		{
			bool flag=0;
			if(a<0&&b<0) a=-a,b=-b;
			if(a<0) a=-a,flag=1;
			if(b<0) b=-b,flag=1;
			ll ggcd=gcd(a,b);
			a/=ggcd;
			b/=ggcd;
			if(flag) a=-a;
			return *this;
		}
		void swap(){std::swap(a,b);}
		Frac _swap(const Frac& t)const{return Frac(t.b,t.a);}
		ll FastPow(ll x,ll p,ll mod)const
		{
			ll ans=1,bas=x;
			for(;p;bas=bas*bas%mod,p>>=1)
				if(p&1) ans=ans*bas%mod;
			return ans;
		}
	public:
		ll a,b;
		Frac(ll A=0,ll B=1){a=A,b=B;}
		void red()
		{
			bool flag=0;
			if(a<0&&b<0) a=-a,b=-b;
			if(a<0) a=-a,flag=1;
			if(b<0) b=-b,flag=1;
			ll ggcd=gcd(a,b);
			a/=ggcd;
			b/=ggcd;
			if(flag) a=-a;
			return;
		}
		void show()const{std::cout<<a<<'/'<<b<<endl;}
		ll to_int(const ll& mod=998244353)const{return a*FastPow(b,mod-2,mod)%mod;}
		Frac abs()const{return Frac(abs(a),abs(b));}
		Frac operator =(const Frac& t){return a=t.a,b=t.b,t;}
		bool operator ==(const Frac& t)const{Frac A(*this),B(t);return (A.reduce().a==B.reduce().a)&&(A.b==B.b);}
		bool operator !=(const Frac& t)const{Frac A(*this),B(t);return (A.a!=B.a)||(A.b!=B.b);}
		bool operator >(const Frac& t)const{Frac A(*this),B(t);ll ggcd=gcd(A.reduce().b,B.reduce().b);return B.b/ggcd*A.a>A.b/ggcd*B.a;}
		bool operator <(const Frac& t)const{Frac A(*this),B(t);ll ggcd=gcd(A.reduce().b,B.reduce().b);return B.b/ggcd*A.a<A.b/ggcd*B.a;}
		bool operator >=(const Frac& t)const{Frac A(*this),B(t);ll ggcd=gcd(A.reduce().b,B.reduce().b);return B.b/ggcd*A.a>=A.b/ggcd*B.a;}
		bool operator <=(const Frac& t)const{Frac A(*this),B(t);ll ggcd=gcd(A.reduce().b,B.reduce().b);return B.b/ggcd*A.a<=A.b/ggcd*B.a;}
		Frac operator +(const Frac& t)const{ll ggcd=gcd(b,t.b);return Frac(b/ggcd*t.a+t.b/ggcd*a,b/ggcd*t.b).reduce();}
		Frac operator +=(const Frac& t){return *this=*this+t;}
		Frac operator *(const Frac& t)const{return Frac(a*t.a,b*t.b).reduce();}
		Frac operator *=(const Frac& t){return *this=*this*t;}
		Frac operator -(const Frac& t)const{return (*this+Frac(-t.a,t.b)).reduce();}
		Frac operator -=(const Frac& t){return *this=*this-t;}
		Frac operator /(const Frac& t)const{return (t._swap(t)*(*this)).reduce();}
		Frac operator /=(const Frac& t){return *this=*this/t;}
		Frac operator -()const{return Frac(-a,b);}
};
const int MAXN=1e6+5;
int n;
Frac<int>cl0(0,1);
Frac<int>cl1(1,1);
Frac<int>cl2(2,1);
Frac<int>INF(0x3f3f3f3f,1);
vector<int>g[MAXN];
Frac<int>res;
Frac<int>dp1[MAXN]; 
Frac<int>dp2[MAXN];
int val[MAXN];
int x,y;
void print(Frac<int>re)
{
	re.red();
 	re.show();
 	return;
}
Frac<int>Min(Frac<int>x,Frac<int>y)
{
	return x<y?x:y;
}
Frac<int>Max(Frac<int>x,Frac<int>y)
{
	return x>y?x:y;
}
void dfs(int x,int f)
{
	bool sf=0;
	for(int i=0;i<g[x].size();i++)
	{
		int v=g[x][i];
		if(v==f)
		{
			continue;
		}
		sf=1;
		dfs(v,x);
		if(val[x]==1)
		{
			dp1[x]=Max(dp1[x],dp1[v]+cl1);
			dp2[x]=Max(dp2[x],dp2[v]+cl1);		
		}		
		if(val[x]==2)
		{
			dp2[x]=Max(dp2[x],dp1[v]+cl1);
		}
	}
	if(!sf)
	{
		if(val[x]==1)
		{
			dp1[x]=cl1;
		}
		if(val[x]==2)
		{
			dp2[x]=cl2;
		}
		
		return;
	}
	int fir1=0,fir2=0,sec1=0,sec2=0;
	for(int i=0;i<g[x].size();i++)
	{
		int v=g[x][i];
		if(f==v)
		{
			continue;
		}
		if(dp2[v]>=dp2[fir2])
		{
			sec2=fir2;
			fir2=v;
		}
		else if(dp2[v]>dp2[sec2])
		{
			sec2=v;
		}
		if(dp1[v]>=dp1[fir1])
		{
			sec1=fir1;
			fir1=v;
		}
		else if(dp1[v]>dp1[sec1])
		{
			sec1=v;
		}
	}
	if(val[x]==1)
	{
		if(fir1==fir2)
		{
			res=Min(res,(cl2/(dp1[sec1]+dp2[fir2]+cl1)));
			res=Min(res,(cl2/(dp1[fir1]+dp2[sec2]+cl1)));
		}
		else
		{
			res=Min(res,(cl2/(dp1[fir1]+dp2[fir2]+cl1)));
		}
		res=min(res,(cl1/(dp1[fir1]+dp1[sec1]+cl1)));
	}
	if(val[x]==2) 
	{
		res=min(res,(cl2/(dp1[fir1]+dp1[sec1]+cl1)));
//		print((cl2/(dp1[fir1]+dp1[sec1]+cl1)));
//		printf("%d %d\n",fir1,sec1);
//		print(dp1[fir1]);
//		print(dp1[sec1]);
	}
	
}

int main() {
	
	
	res=INF; 
    scanf("%d",&n);
    for(int i=1;i<n;i++)
	{
		scanf("%d %d",&x,&y);
		g[x].push_back(y);
		g[y].push_back(x);
	 } 
	 
	 for(int i=1;i<=n;i++)
	 {
	 	scanf("%d",&val[i]);
	 	dp1[i]=cl0;
	 	dp2[i]=cl0;
	 	Frac<int>dsf(val[i],1);
	 	res=Min(res,dsf);
	 }
	 //print();
	 //printf("\n");
 	dfs(1,0);
 	print(res);
}
posted @ 2022-02-11 09:03  kid_magic  阅读(75)  评论(0编辑  收藏  举报