2018 2 6 佇列 次小生成樹

2021-08-15 12:42:57 字數 3470 閱讀 3904

標籤: 考試

本次考試排名:rank23

本次考試題目推薦:數字遊戲(細節巨多),麥樂雞翅(可後悔堆)

板子:次小生成樹(資料較弱)

今天沒有心路歷程(angry)

對自己算作一次警告

認識到了游泳的巨大安全隱患之後,小朋友們都決定不去游泳了。於是,游泳館冷清了下來。為了能因時制宜、因事制宜,游泳館決定在游泳專案之外,還開設頭腦風暴專案。頭腦風暴當中有這樣一道題目:給出乙個len位的數字a,你可以刪除數字a當中的n位,刪除之後得到乙個len-n位的數字b,你的目標就是使這個數字b最小。

對於 50%的資料,len<=100000.

對於 100%的資料,len<=5000000 , 0<=n<=len.

利用單調棧,從前往後盡力去維護遞增,只要仍有刪除次數就維護下去。說白了是貪心即可(每次刪除左邊第乙個比右邊大的)

好了,上**

int max=cnt-n;

for(int i=1;i<=cnt;i++)

if(!flag)puts("0");

在太行山路上,有一家麥樂雞翅的生意火爆。因為好吃,所以賣的特別好。排隊的人就特別多,經常有很多人買不到雞翅。雞翅會在每分鐘烤出xixi

個,每分鐘也只會賣給乙個客人,第i個客人需要買yiyi

個。因為生意火爆,老闆可以選擇在這分鐘不賣給這個客人雞翅,或者賣給這個顧客他需要的雞翅,如果現在剩餘的雞翅不夠,那就肯定不能賣給這個客人。無論這個客人能否買到雞翅,他必須離開隊伍。現在給定 n 分鐘,且已經知道每分鐘烤出的雞翅個數xixi

,也知道每個客人需要雞翅的yiyi

個數,現在老闆想知道,如何合理安排賣給與拒絕,最多可以滿足多少人

50% 資料保證 n<=1000

100% 1<=n<=250000 xi,yi 都在[0,10^9]範圍內

弄乙個大根堆出來,然後後悔就ok了,甚是簡單(那你怎麼不現切)

rg ll sum=0,now;

for(rg int i=1;i<=n;i++)

else

if(b[i]sum+=now-b[i];

chi.pop();

chi.push(b[i]);

}}rg int ans=chi.size();

cout《小 c 最近學了很多最小生成樹的演算法,prim演算法、kurskal演算法、消圈演算法等等。 正當小c洋洋得意之時,小p又來潑小c冷水了。小p說,讓小c求出乙個無向圖的次小生成樹,而且這個次小生成樹還得是嚴格次小的,也就是說:如果最小生成樹選擇的邊集是em,嚴格次小生成樹選擇的邊集是 es,那麼需要滿足:(value(e) 表示邊 e 的權值)

資料中無向圖無自環;

50% 的資料 n≤2 000 m≤3 000;

80% 的資料 n≤50 000 m≤100 000;

100% 的資料 n≤100 000 m≤300 000 ,邊權值非負且不超過 10^9 。

最小生成樹與次小生成樹一定只有一條邊的長度不同(證明感性思考一下就好了),因而我們要先構出一棵最小生成樹,然後再從邊集中選入某條邊以此來代替最小生成樹上的邊。由於我們新加入的邊所連線的兩點x,y必定是在同乙個集合中的了,因而我們考慮將x->y路徑上某條邊斷掉,那麼為了使修改後的邊權和盡可能接近最小生成樹的邊權和,我們查詢x->y路徑上的最大值,因而這個可以用倍增或樹剖+線段樹完成(筆者用的是倍增)

但是!!!(這個題目這麼簡單就太天真了!)會存在如下情況

有多組最小生成樹滿足條件

因而我們還需要維護乙個次大值,在有多組最大滿足下輸出次大就好了!這樣是不是可以解決問題了!好了,還有一些細節要處理,筆者放在**裡了,希望對大家有幫助(這個題目要思想有思想,要難度有難度,要細節有細節)

#include

#include

#include

#include

using

namespace

std;

#define rg register

#define ll long long

#define inf 1e18

const

int maxn=3e5+5;

int n,m;

ll ans=inf,s;

inline

int read()

struct edgee[maxn];

inline

bool cmp(edge a,edge b)

struct handa[maxn<<1];

int head[maxn],cnt,tot;

inline

void link(int u,int v,int z)

; head[u]=cnt;

}int dep[maxn],f[maxn][26];

ll g1[maxn][26],g2[maxn][26];

void dfs(int u,int fa)

}inline

void kru()

if(cao==n-1)break;

}}inline

void match(int &u,int j,ll &maxx,ll &semx)

else

if(maxxelse

u=f[u][j];

}inline ll lca(int u,int v,int stand)

return maxx;

}for(rg int j=20;j>=0;j--)

}match(u,0,maxx,semx);match(v,0,maxx,semx);

if(semx==-inf)return -inf;

if(maxx==stand)return semx;

return maxx;

}int main()

; for(rg int i=1;i<=n;i++)bcj[i]=i;

sort(e+1,e+m+1,cmp);

for(rg int i=0;i<=20;i++)g1[1][i]=g2[1][i]=-inf;

kru();dep[1]=1;dfs(1,0);

for(rg int j=1;j<=20;j++)

else}}

rg int x,y;

for(rg int i=1;i<=m;i++)

cout

0;}

最小生成樹 次小生成樹

一 最小生成樹 說到生成樹首先要解釋一下樹,樹是乙個聯通的無向無環圖,多棵樹的集合則被稱為森林。因此,樹具有許多性質 1.兩點之間的路徑是唯一的。2.邊數等於點數減一。3.連線任意兩點都會生成乙個環。對於乙個無向聯通圖g的子圖,如果它包含g的所有點,則它被稱為g的生成樹,而各邊權和最小的生成樹則被稱...

次小生成樹

演算法引入 設g v,e,w 是連通的無向圖,t是圖g的一棵最小生成樹 如果有另一棵樹t1,滿足不存在樹t t t1 則稱t1是圖g的次小生成樹 演算法思想 鄰集的概念 由t進行一次可行交換得到的新的生成樹所組成的集合,稱為樹t的鄰集,記為n t 設t是圖g的最小生成樹,如果t1滿足 t1 min,...

次小生成樹

分類 圖論 2013 02 12 15 03 32人閱讀收藏 舉報次小生成樹 在求最小生成樹時,用陣列path i j 來表示mst中i到j最大邊權。求完後,直接列舉所有不在mst中的邊,把它加入到mst中構成一棵新的樹,且該樹有環,此環是由剛加入的邊 i,j 造成的,所以可以通過刪除path i ...