第一行包含三個由空格隔開的整數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的。然後隨手給自己的替代方法舉...