bzoj3206 Apio2013 道路費用

2022-05-02 04:06:10 字數 2837 閱讀 2759

第一行包含三個由空格隔開的整數n,m和k。接下來的 m行描述最開始的m 條道路

。這m行中的第i行包含由空格隔開的整數ai,bi和c i,表示有一條在a i和b i之間,費用為c i的雙向道路。接下

來的k行描述新建的k條道路。這 k行中的第i行包含由空格隔開的整數 xi和yi,表示有一條連線城鎮xi和yi新道路

。最後一行包含n個由空格隔開的整數,其中的第j個為pj,表示從城鎮j 前往城鎮 1的人數。輸入也滿足以下約束

條件。1 ≤ n ≤ 100000;1 ≤ k ≤ 20;1 ≤ m ≤ 300000;對每個i和j,1 ≤ ci, pj ≤ 10^6;

你的程式必須輸出恰好乙個整數到標準輸出,表示能獲得的最大的收入。

5 5 1

3 5 2

1 2 3

2 3 5

2 4 4

4 3 6

1 3

10 20 30 40 50

400在樣例中, mr. greedy應該將新道路(1,3)的費用設定為 5分錢。在這個費用下,他可以選擇道路(3,5),(1,2),(2,4)和(1,3)來最小化總費用,這個費用為   14。從城鎮 3出發的 30個人和從城鎮 5出發的 50個人將經過新道路前往城鎮 1,因此他可以獲得為(30+50)_5=400 分錢的最好收入。如果我們這樣做,將新道路(1,3)的費用設定為 10分錢。根據傳統的限制,mr. greedy必須選擇(3,5),(1,2),(2,4)和(2,3),因為這是唯一費用最小的集合。因此,在嘉年華的過程中道路(1,3)將沒有任何收入。

正解:最小生成樹+搜尋。

這道題還是有點碼的,我寫了好久。。

首先$k\leq20$,我們可以想到列舉選邊的集合,然後計算答案。

但是有乙個問題,原圖特別大,我們每次選邊計算答案肯定不行,怎麼辦呢?

我們可以發現,有一些邊是無論如何都會在原圖上的,我們只要強制把$k$條邊先加進去,再看有哪些邊可以和這$k$條邊構成最小生成樹就行了。

然後我們可以把原圖縮點變成乙個$k+1$個點的圖,但是邊數還是$k^$級別的。

那麼我們可以再去掉那$k$條邊,做一遍最小生成樹,這樣的邊是會出現在原圖上的,其他邊肯定不會在圖上,然後邊數就變成$k$條了。

然後我們列舉$k$條邊是否在圖上,強制把搜尋出來的邊加進圖中,再看這些邊的取值。

只要把沒加進圖的邊在樹上走一下,經過的邊邊權取個$min$就行了。

1 #include 2

#define il inline

3#define rg register

4#define ll long long

5#define n (300010)67

using

namespace

std;89

struct egg[n],g[n],e[n];

1011

intbel[n],a[n],st[n],fa[n],vis[n],n,m,k,top,cnt,ecnt;

12ll val[n],ans;

1314 il int

gi()

2122 il int cmp(const e &a,const e &b)

2324 il int find(rg int x)

2526

struct

graphg[n<<1

];29

30int

head[n],fa[n],dep[n],dis[n],num;

31ll sz[n];

3233 il void insert(rg int

from,rg int to,rg int

fg),head[from]=num; return;35

}3637 il void dfs1(rg int x,rg int

p)43

return;44

}4546 il void dfs2(rg int x,rg int

p)52

return;53

}5455 il void getlca(rg int u,rg int v,rg int

w)60

return;61

}6263 il ll getans(rg int x,rg int

p)69

return

res;70}

7172

}g;73

74il ll check()

80for (rg int i=1,x,y;i<=m;++i)

84 g.dfs2(1,0

);85

for (rg int i=1;i<=m;++i) if (!vis[i]) g.getlca(g[i].u,g[i].v,g[i].w);

86return g.getans(1,0

);87}88

89 il void dfs(rg int

x)93

94int

main()

105 sort(g+1,g+m+1

,cmp);

106for (rg int i=1,x,y;i<=m;++i)

110for (rg int i=1;i<=n;++i) a[i]=gi(),fa[i]=i; g.dfs1(1,0

);111

for (rg int i=1;i<=k;++i) e[i].u=bel[e[i].u],e[i].v=bel[e[i].v];

112for (rg int i=1,x,y;i<=m;++i)

117 m=ecnt; for (rg int i=1;i<=m;++i) g[i]=gg[i];

118 dfs(1),cout

119 }

bzoj4070 APIO2015 耶加達的摩天樓

time limit 10 sec memory limit 256 mb submit 189 solved 70 submit status discuss 印尼首都耶加達市有 n 座摩天樓,它們排列成一條直線,我們從左到右依次將它們編號為 0 到 n 1。除了這 n 座摩天樓外,耶加達市沒有其...

BZOJ4585 Apio2016 煙火表演

烟花表演是最引人注目的節日活動之一。在表演中,所有的烟花必須同時 為了確保安 全,烟花被安置在遠離開關的位置上,通過一些導火索與開關相連。導火索的連線方式形成 一棵樹,烟花是樹葉,如 圖1 所示。火花從開關出發,沿導火索移動。每當火花抵達乙個分 叉點時,它會擴散到與之相連的所有導火索,繼續燃燒。導火...

bzoj 3624 Apio2008 免費道路

這題一看,不是一句話題意,不想做。題意就不說了吧。首先想到的肯定是最小生成樹。然後我就想起了以前的某道題。好吧,記不大清了。我一開始的想法是貪心替換。就是先把圖構好,然後用0去換1 也就是先把全部1跑一次,然後把0跑一次,先把必要的0拿出來,然後再在剩下的0裡面選替代1的。然後隨手給自己的替代方法舉...