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

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