小Y的问题

来源:互联网 发布:多线程编程 java 编辑:程序博客网 时间:2024/04/29 02:40

这里写图片描述

30分做法:n^4枚举边.
100分做法:
枚举每一条边,设两个端点为x,y;
我们通过组合公式来计算 Y 的个数,每一次加上C(num[x]-1)*(num[y]-1);
通过记连接一个点的边的最大值,次大值,第三大值。
加上除去枚举的边外x连接的最大的两条边,以及y连接的除去… 之后最大的边。
然后再将x和y换过来,重复一遍。

重复上述操作。

#include<cstdio>#include<iostream>#include<cmath>#include<cstring>#include<algorithm>#include<queue>#define LL long longusing namespace std;int n;LL maxn,ans;struct H{    LL m1,m2,m3;    int t1,t2,t3;}a[200009];//点 struct HH{    LL x,y,l;}b[200009];//边 LL cnt,num[200009];void ex(int x,int y,int z){    if(z>=a[x].m1)    {           a[x].m3=a[x].m2;        a[x].m2=a[x].m1;        a[x].m1=z;        a[x].t3=a[x].t2;        a[x].t2=a[x].t1;        a[x].t1=y;    }    else     if(z>=a[x].m2)    {        a[x].t3=a[x].t2;        a[x].t2=y;        a[x].m3=a[x].m2;        a[x].m2=z;      }    else     if(z>a[x].m3)    {        a[x].t3=y;        a[x].m3=z;    }}LL C(LL x)//从x个中任选2个 !一定要开LL {return x*(x-1)/2;}int main(){    scanf("%d",&n);    for(int i=1;i<=n;i++){        a[i].m1=a[i].m2=a[i].m3=0;        a[i].t1=a[i].t2=a[i].t3=i;    }     for(int i=1;i<n;i++)    {        int x,y,z;        scanf("%d%d%d",&x,&y,&z);        b[++cnt]=((HH){x,y,z});        ex(x,y,z);ex(y,x,z);        num[x]++;num[y]++;    }    for(int i=1;i<=cnt;i++)    {        int x=b[i].x,y=b[i].y;        LL len=b[i].l;        if(num[x]>=3&&num[y]>=2)        {            LL p=0;            if(a[x].t1==y) p=a[x].m2+a[x].m3;            else if(a[x].t2==y) p=a[x].m1+a[x].m3;            else p=a[x].m1+a[x].m2;            if(a[y].t1==x) p+=a[y].m2;            else p+=a[y].m1;            p+=len;            maxn=max(p,maxn);            ans+=C(num[x]-1)*(num[y]-1);        }        int tmp=x;x=y,y=tmp;        if(num[x]>=3&&num[y]>=2)        {            LL p=0;            if(a[x].t1==y) p=a[x].m2+a[x].m3;            else if(a[x].t2==y) p=a[x].m1+a[x].m3;            else p=a[x].m1+a[x].m2;            if(a[y].t1==x) p+=a[y].m2;            else p+=a[y].m1;            p+=len;            maxn=max(p,maxn);            ans+=C(num[x]-1)*(num[y]-1);        }    }    printf("%lld\n%lld",ans,maxn);    return 0;}