基站建设(三元环计数+根号分治 / bitset)
基站建設
- problem
- solution
- code
problem
給定 nnn 個地點,以及每個地點的可靠度 RiR_iRi?。
有 mmm 條光纖架,每一條連接兩個不同的地點,且是雙向的。
測試基站由 444 個信號塔,有 222 個主信號塔和 222 個副信號塔。
要求主信號塔必須與其余三個塔相連,副信號塔必須與所有主信號塔相連。
每個地點都只能建一個信號塔,基站的可靠度為兩個主信號塔所在地點可靠度+1+1+1的乘積再加上兩個副信號塔所在地可靠度的乘積。即 (Ri+1)(Rj+1)+RaRb(R_i+1)(R_j+1)+R_aR_b(Ri?+1)(Rj?+1)+Ra?Rb?。
求測試基站的最大可靠度。
n≤3e5,1s,512MBn\le 3e5,1s,512MBn≤3e5,1s,512MB。
solution
observation:滿足條件的子圖其實上是有一條公共邊的兩個三元環。
求解公式并沒有什么特殊性質,所以很有可能是需要枚舉三元環的。
枚舉三元環既可以枚舉三個點,也可以枚舉三條邊,選擇不同帶來的時間效率也有所不同。
考慮根號分治。
對于度數 <m<\sqrt{m}<m? 的點,枚舉其兩條出邊再判斷兩條邊的入點之間是否有邊。
度數 >m>\sqrt{m}>m? 的點,總個數不超過 m\sqrt{m}m? 個。直接枚舉三個點。
時間復雜度均為 O(mm)O(m\sqrt{m})O(mm?)。
上面的是正解,下面的是我在考場上自己想的做法。
最暴力的就是考慮一條邊,這條邊是連接主信號塔 u,vu,vu,v 之間的。
其實剩下的就是找 u,vu,vu,v 連接的點的交集之中可靠度最大的兩個點。
暴力枚舉邊就是 O(m2)O(m^2)O(m2) 的。但是一旦使用 bitset 就不一樣了。
直接 bitset 處理每個點直接相連的點的集合,將 u,vu,vu,v 的 bitset 直接取 &。
然后 bitset 也自帶快速找到為 111 的位置。
空間復雜度 O(n2)O(n^2)O(n2)。不卡!
時間復雜度是 O(nmω)O(\frac{nm}{\omega})O(ωnm?)
反正跑得挺快的。
code
#include <bits/stdc++.h> using namespace std; #define maxn 50005 #define maxm 200005 bitset < maxn > g[maxn]; pair < int, int > E[maxm]; int R[maxn]; int n, m;int main() {freopen( "station.in", "r", stdin );freopen( "station.out", "w", stdout );scanf( "%d %d", &n, &m );for( int i = 1;i <= n;i ++ ) scanf( "%d", &R[i] );for( int i = 1, u, v;i <= m;i ++ ) {scanf( "%d %d", &u, &v );E[i] = { u, v };g[u][v] = g[v][u] = 1;}int ans = 0;for( int i = 1;i <= m;i ++ ) {int u = E[i].first, v = E[i].second;bitset < maxn > son = g[u] & g[v];son[u] = son[v] = 0;int max1 = 0, max2 = 0;for( int k = son._Find_first();k != son.size();k = son._Find_next( k ) ) {if( R[k] > max1 ) max2 = max1, max1 = R[k];else if( R[k] > max2 ) max2 = R[k];}if( ! max1 or ! max2 ) continue;ans = max( ans, ( R[u] + 1 ) * ( R[v] + 1 ) + max1 * max2 );}printf( "%d\n", ans );return 0; }總結
以上是生活随笔為你收集整理的基站建设(三元环计数+根号分治 / bitset)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 铺地毯(矩形的交+前后缀矩形交)
- 下一篇: 高考补脑提高记忆力的菜谱 帮助高考生补脑