树(tree)

树(tree)

题目描述

 

给定一棵nn个节点的树,树上每个点有点权xixi 。

对于一条路径i1,i2,…,ik,定义路径的权值为xi1×xi2×⋯×xik/k

现在要找一条权值最小的路径,请以分数的形式输出路径的权值。

 

输入

 

第一行包括一个整数nn。

第二行到第nn行每行两个整数x,y(1≤x,y≤n)x,y(1≤x,y≤n),表示一条xx到yy的树边。

第n+1n+1行到第2n2n行,依次为x1,x2,…,xnx1,x2,…,xn。

 

输出

 

输出答案的分数形式,形如a/ba/b,其中a,ba,b互质且为正整数。

 

样例输入

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

样例输出

1/3

提示

 

对于100%100%的数据,n≤106,xi≤109n≤106,xi≤109。

测试点编号

nn

其它性质

1,2,3,41,2,3,4

103103

 

5,6,75,6,7

106106

不存在一个节点的度数超过22

8,9,108,9,10

106106

 

 

 

来源

南外NOIP2017模拟


这题有点诡异。。。

如果整棵树上的最小值大于一,答案就是最小值,因为乘起来除以2肯定不优

那么我们考虑树上最长的1的序列

如果有111121111这样若干1夹一个2的答案,那么它可能是答案。

不然就是最长1的序列。

证明的话,分分类吧。。

#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<cmath>
#define maxn 1000005
using namespace std;
int n,head[maxn],f[maxn],g[maxn],up[maxn],w[maxn];
int fl,tot,t1,t2,ans1,ans2;
struct node{
    int v,nex;
}e[maxn*2];
void lj(int t1,int t2){
    e[++tot].v=t2;e[tot].nex=head[t1];head[t1]=tot;
}
void dfs(int k,int fa){
    int Max=0,max2=0;
    for(int i=head[k];i;i=e[i].nex){
        if(e[i].v!=fa){
            dfs(e[i].v,k);
            if(f[e[i].v]>Max){
                max2=Max;
                Max=f[e[i].v];
            }
            else if(f[e[i].v]>max2)max2=f[e[i].v];
        }
    }
    if(w[k]==1){
        f[k]=Max+1;
        if(max2>0)g[k]=max2+1;
    }
    else f[k]=g[k]=0;
}
void dfs2(int k,int fa){
    if(w[fa]!=1)up[k]=0;
    else {
        if(f[fa]==f[k]+1)up[k]=g[fa];
        else up[k]=f[fa];
        up[k]=max(up[k],up[fa]+1);
    }
    for(int i=head[k];i;i=e[i].nex){
        if(e[i].v!=fa){
            dfs2(e[i].v,k);
        }
    }
}
void work(int k,int fa){
    if(w[k]==1){
        ans1=max(ans1,max(f[k]+g[k]-1,f[k]+up[k]));
        //cout<<k<<' '<<f[k]<<' '<<g[k]<<' '<<max(f[k]+g[k]-1,f[k]+up[k])<<endl;
    }
    if(w[k]==2){
         
        int ma=0;
        for(int i=head[k];i;i=e[i].nex){
            if(e[i].v!=fa)ma=max(ma,f[e[i].v]);
        }
        ans2=max(ans2,max(ma+g[k]-1,ma+up[k]));
    }
    for(int i=head[k];i;i=e[i].nex){
        if(e[i].v!=fa){
            work(e[i].v,k);
        }
    }
}
int main(){
    freopen("tree.in","r",stdin);
    freopen("tree.out","w",stdout);
    cin>>n;
    for(int i=1;i<n;i++){
        scanf("%d%d",&t1,&t2);
        lj(t1,t2);lj(t2,t1);
    }
    int Min=1e9;
    for(int i=1;i<=n;i++){
        scanf("%d",&w[i]);
        Min=min(Min,w[i]);
    }
    if(Min>1){printf("%d/1\n",Min);return 0;}
    dfs(1,0);
    dfs2(1,0);up[1]=0;
    //for(int i=1;i<=n;i++)cout<<i<<' '<<f[i]<<' '<<g[i]<<' '<<up[i]<<endl;
    work(1,0);
    ans2++;
    if(ans1*2>=ans2){
        printf("1/%d\n",ans1);
    }
    else {
        if(ans2%2==0){
            ans2/=2;
            printf("1/%d\n",ans1);
        }
        else printf("2/%d\n",ans2);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/liankewei123456/article/details/82822422