1007: 小Y的问题【TYVJ2016国庆赛D1T2】

Description
    有个孩子叫小Y,一天,小Y拿到了一个包含n个点和n-1条边的无向连通图,图中的点用1~n的整数编号。小Y突发奇想,想要数出图中有多少个“Y字形”。

    一个“Y字形”由5个不同的顶点A、B、C、D、E以及它们之间的4条边组成,其中AB、BC、BD、DE之间有边相连,如下图所示。

    同时,无向图中的每条边都是有一定长度的。一个“Y字形”的长度定义为构成它的四条边的长度和。小Y也想知道,图中长度最大的“Y字形”长度是多少。

Input
第一行包含一个整数n,表示无向图的点数。

接下来n行,每行有3个整数x、y、z,表示编号为x和y的点之间有一条长度为z的边。



Output
输出包含2行。

第1行包含一个整数,表示图中的“Y字形”的数量。

第2行包含一个整数,表示图中长度最大的“Y字形”的长度。

Sample Input
7
1 3 2
2 3 1
3 5 1
5 4 2
4 6 3
5 7 3
Sample Output
5
9
HINT

TYVJ2016国庆赛D1T2

【输入输出样例1说明】

图中共有5个“Y字形”,如图中用红色标出的部分所示。

1
其中,长度最大的“Y字形”是编号3、5、7、4、6的顶点构成的那一个,长度为9。

【数据规模与约定】

对于30%的数据,n≤10

对于60%的数据,n≤2,000

对于100%的数据,n≤200,000,1≤x,y≤n,1≤z≤10,000

    以下所有数字以图片中第一个为例。
第一问: 枚举,但要枚举的这一个点,与之构成的图形,最好不要有重复,并且要尽量快。因此,找类似3的中心(因为以它为中心不会有重复,且位于中心位置,循环少),枚举每一个点,以此点为中心,首先此点的度数要先大于等于3。再找要求的图形。 for一遍n个点 再for其相邻的点,记录长度为2的链的个数然后直接公式work()即可; 时间复杂度O(2n)

    首先,暴力枚举。如果枚举类似7点的位置会超时。因此,找其中心3 枚举每一个点,并以此点作为中心往外找。
朴素做法,大暴力,找1,2,5,7;
显然,会超时;
优化:记录最大值,次大值,第三大值(中心点有三个度最坏情况下 用三个)。然后用一个pair 记录最值得个数。
已经记录了最大值,如何保证找到的以此点为中心的长度最大。先找长度为2 的链的权值还是先找相邻的两个点权值?
显然,可以证得,先找长度为2 的链再找相邻两点,或先找相邻的最大两个点再找长为2的链,长度最大的值一定为其中之一。
因为若长为2的链不是最长的或相邻两点不是最大的,一定有更大的解。
以此点为中心的图形最长值是上述两种方法的值之一,但不确定是哪一个。因此走两遍即可。
#include <iostream>
#include <cstdio>
#include <vector>
using namespace std;
#define mp make_pair
#define LL long long 
LL n,ans1,ans2;
vector <pair<LL,LL> > v[222222];
pair <LL ,LL >  mx[222222][5];
LL ss,s1,s2,s3,s4,s11,s22,s33,s44,s55;
LL gs[222222];
LL sy2[5];
LL getint()
{
    LL x=0,f=1; char ch=getchar();
    while (ch<'0' || ch >'9') {if (ch=='-') f=-1; ch=getchar();}
    while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();}
    return x*f;
}
LL bj(LL x,LL z)
{
    // first    second
    if(z>mx[x][1].first)
    {
        mx[x][3]=mx[x][2];
        mx[x][2]=mx[x][1];
        mx[x][1]=mp(z,1);
    }
    else
        if(z==mx[x][1].first)
            mx[x][1].second++;
        else
            if(z>mx[x][2].first)
            {
                mx[x][3]=mx[x][2];
                mx[x][2]=mp(z,1);
            }
            else
                if(z==mx[x][2].first)   mx[x][2].second++;
                else
                    if(z>mx[x][3].first)        mx[x][3]=mp(z,1);
                    else
                        if(z==mx[x][3].first)   mx[x][3].second++;

}
LL work(LL x)
{
    return x*(x-1)/2;
}
LL work2(LL now,LL nn,LL sy,LL cf)
{
    if(mx[now][nn].first>cf||mx[now][nn].first<cf)
    {
        LL x=mx[now][nn].second;
        if(x>=sy) {s4+=mx[now][nn].first*sy;sy2[int(nn)]-=x;return 0;}
        else 
        {
            s4+=mx[now][nn].first*x;
            sy2[nn]=0;
            work2(now,nn+1,sy-x,cf);
        }
    }
    else
        if(mx[now][nn].first==cf)
        {
            LL x=mx[now][nn].second;
            if(x>1)
            {
                x--;
                if(x>=sy)
                    {s4+=mx[now][nn].first*sy;return 0;}
                else
                {
                    s4+=mx[now][nn].first*x;
                    work2(now,nn+1,sy-x,cf);
                }
            }
            else
            {
                work2(now,nn+1,sy,cf);
            }
        }
}
LL work3(LL fa,LL son,LL len,LL nn)
{
    if(mx[son][nn].first>len||mx[son][nn].first<len) 
    {
        s1+=mx[son][nn].first;return 0;
    }
    else
    {
        if(mx[son][nn].first==len) 
        {
            if(mx[son][nn].second>1) 
            {
                s1+=mx[son][nn].first;return 0;
            }
            else
            {
                work3(fa,son,len,nn+1);
            }
        }
    }
}
int pd(int now,int son,int len,int nn)
{
    if(nn>3) return 1;
    if(len==mx[now][nn].first)
    {
        if(sy2[nn]>0) 
            return 1;
        else
            return 0;
    }
    else
    {
        if(len<mx[now][nn].first)
        {
            return pd(now,son,len,nn+1);
        }
    }
}
int main()
{
    // freopen("question3.in","r",stdin);
    // freopen("question9.out","w",stdout); 
    n=getint();
    for(int i=1;i<n;i++)
    {   
        LL x=getint(),y=getint(),z=getint();
        bj(x,z);
        bj(y,z);
        v[x].push_back(mp(y,z));
        v[y].push_back(mp(x,z));
    }
    for(int i=1;i<=n;i++)
    {
        for(int j=0;j<v[i].size();j++)
        {
            LL son=v[i][j].first;
            if((LL)( v[son].size() )>1)
                gs[i]+=v[son].size()-1;
        }
    }
    for(int i=1;i<=n;i++)
    {
        // cout<<gs[i]<<endl;
        if(v[i].size()>=3)
        {
            ss=0;
            ss=work(v[i].size()-1);
            ans1+=ss*gs[i];
            // work2(i,1,3);
            //s1=0;
            s1=s2=s3=s4=s11=s22=s33=s44=0;//初始化
            for(int j=0;j<v[i].size();j++)/********第一次找:begin.  先找最大的长度为2的链 再找不重复的两个相邻点*******/
            {
                s1=v[i][j].second;
                work3(i,v[i][j].first,v[i][j].second,1);
                if(s1>s2)
                {
                    s2=s1;
                    s3=v[i][j].second;
                }
            }
            work2(i,1,2,s3);
            /***********第一次找:end********************/
            // s11=s2;
            ans2=max(ans2,s4+s2);
            s1=s2=s3=s4=0;//初始化/***********第二次找:begin。 先找最大的两个相邻点,再找不重复的最大的长度为2的链 **********/
            for(int j=1;j<=3;j++)
                sy2[j]=mx[i][j].second;
            work2(i,1,2,0);
            for(int j=0;j<v[i].size();j++)
            {
                s1=v[i][j].second;
                if(pd(i,v[i][j].first,v[i][j].second,1))
                {
                    work3(i,v[i][j].first,v[i][j].second,1);
                    if(s1>s2)
                    {
                        s2=s1;
                        s3=v[i][j].second;
                    }
                }
            }/***********第二次找:end。*************/
            // for(int j=0;j<v[i].size();j++)/*************此处为找次大的长度为2 的链。有数据3过不了(之前只找了第一次)*********/
            // {
            //  s1=v[i][j].second;
            //  work3(i,v[i][j].first,v[i][j].second,1);
            //  if(s1>s2&&s1<s11)
            //  {
            //      s2=s1;
            //      s3=v[i][j].second;
            //  }
            // }
            // work2(i,1,2,s3);
            ans2=max(ans2,s4+s2);
        }
    }
    cout<<ans1<<endl<<ans2<<endl;
    return 0;
}
/*
7
1 3 2
2 3 1
3 5 1
5 4 2
4 6 3
5 7 3
*/
/*
10
1 2 40
1 3 80
2 4 81
2 5 81
3 6 21
5 7 45
6 8 68
7 9 41
5 10 72


6
282

*/
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章