(一遍過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...