清北2016 小Y的問題

2021-08-29 12:02:09 字數 1650 閱讀 7582

(一遍過sample,高興的我去測試,80 qwq。。。。。。卡常。。。。。。)

ac程式

30的方法:

看資料:n<=10

這個資料直接打暴力完全ok,列舉四條邊,看是否能滿足y字的要求就行;

60的方法:

資料:n<=2000

這個資料大約能承受o(n^2)的複雜度;

我們不妨列舉度數為三及以上(有三條以上的邊與之相連線)的點:

在圖中可以看出b的度數為三:

由b延伸出三條邊:我們可以分別把ab,bc,bd作為中心邊;

然後列舉b點除bd邊外的邊的個數(假設個數為x),選出兩條作為一種方案,根據組合數的排列公式,共有:x*(x-1)/2種方案,列舉d相連(除bd外)的邊的個數(假設個數為y),根據乘法原則:便可以得出y的方案數:

x*(x-1)/2*y;

這樣第一問就解決了;

第二問:最大的y邊和的權值:

我們可以列舉b點除bd邊外邊的最大值和次大值,和d點除bd外邊的最大權值,加上bd,就是此時的最大權值和。      

ac做法

資料:n<=200000

顯然承受不了o(n^2)的複雜度.................

我們可以用o(n)的演算法,優化一下60的演算法;

我們可以對b點和d點的邊數進行預處理;

那麼y字數的個數公式就可以是:

(degree[b]-1)(degree[b]-2)/2*(degree[d]-1);

第二問的話:

我們可以統計出每個點的最大值,次大值,第三大值;那麼顯然就把列舉最大值的複雜度變為了o(1);

那麼這個演算法的複雜度就變為了o(n),可以一遍過。

下面是ac程式,可借鑑(qwq)  

#include#include#define ll long long

using namespace std;

ll n,x,y,z,num,dg[300000],fl[300000][4],ans;

ll ff[300000][4],sum,flagg;

ll head[1500000],next[1500000],to[1500000],v[1500000],ans1;

void add1(ll a,ll b,ll c)

int main()

fl[x][j]=z;ff[x][j]=y;break; } }

dg[y]++;

for(ll j=1;j<=3;j++)

fl[y][j]=z;ff[y][j]=x;break;

} }

} for(ll i=1;i<=n;i++)

}sum+=v[j];

for(ll k=1;k<=3;k++)

}ans1=max(sum,ans1); }}

}}cout<

cout<

fclose(stdin);fclose(stdout);

return 0;

}

小 Y 的問題

大水題一道,合法個數用 乘法原理 組合數公式 具體做法 num i 表示與i相連的點的個數 我們稱圖上的b d邊為中心邊 我們列舉中心邊 列舉兩個點,先看一側的點i,它的鄰接點有num i 個,但是其中乙個點是中心邊的另乙個點,符合條件的點有num i 1個,利用組合數公式可以求出在這些點中選2個的...

清北學堂的小技巧和小收穫

剛來到清北學堂,收穫頗多,首先是李昊大佬的乙個有用的模板 include include include include include include using namespace std 一堆標頭檔案 typedef long long ll typedef long double ld ty...

2016國慶清北Day2T1

pa 題目描述 漢諾塔公升級了 現在我們有n個圓盤和n個柱子,每個圓盤大小都不一樣,大的圓盤不能放在小的圓盤上面,n個柱子從左到右排成一排。每次你可以將一 個柱子上的最上面的圓盤移動到右邊或者左邊的柱子上 如果移動之後是合法的 話 現在告訴你初始時的狀態,你希望用最少的步數將第i 大的盤子移動到第i...