HDU 6350 2018HDU多校賽 第五場 Always Online(圖論 + 並查集 + 組合計數)
大致題意:給你一個仙人掌圖,讓你計算:。
根據去年多校賽某一道題的經驗,很多仙人掌圖的問題,其實可以轉化為樹的問題。所以我們同樣考慮,如果這是一棵樹的話如何去做。注意到表示式裡面的flow(i,j)表示從i到j的最小割或最大流,而在樹上的最小割可以看作是兩點之間連線的最短邊,那麼我們要做的就是統計每一條邊作為最短邊的貢獻。這樣我們不禁就聯想到了之前做過的 Codeforces 915F 。這題是求任意兩點之間路徑上最長邊減去最短邊之差之和。
和那題類似,在不考慮仙人掌圖,而是普通樹的情況下,本題考慮對邊進行排序,然後不斷的並查集合並統計每條邊產生的新貢獻。那麼我們現在考慮,當不是樹的時候,根據仙人掌圖的定義,每個點最多隻能在一個簡單環內部。我們考慮包含這樣一個環的路徑的最小割,這樣的最小割,要麼是普通路徑上的一條邊,要麼是環中的最短邊加上另一條邊。具體可以參見下圖:
我們要麼切掉類似紅色的邊,要麼切掉兩條類似兩條綠色的邊,然後可以證明兩個綠色的邊一定會有一條環中流量最小的邊。既然如此,如果我們找到這條邊,然後把這個權值加入到環中的其他邊中,然後刪掉這條邊,再求最小割對最後結果也不會產生影響。所以我們不妨把所有的環都這麼處理,這樣一個仙人掌圖就會變成一棵樹,我們也就可以按照之前所說的那麼做了。
具體來說,如果找到這個最小的邊呢。我們不妨做一遍最大生成樹,這樣剩下的邊就一定能夠與某些點構成環,而且一定是這些環中的邊裡面流量最小的。然後我們dfs求出fa和dep等資訊,然後遍歷環中的邊,把每條邊的權值加上這個最小流量。之後就用這個新的樹新的邊求解。本題需要考慮的是路徑中的最小值,所以我們邊也是一樣從最大的開始合併。每次並查集合並,然後計算貢獻。
這個貢獻,由於又要考慮上兩個端點i和j,所以還要有一些技巧。具體來說於 Codeforces 724G 有點類似。分別統計每一個連通塊裡面有多少個數在對應二進位制位的值是1和0的個數。合併的時候一起合併即可。還有,最後答案比較坑,需要用到ull。具體見程式碼:
#include<bits/stdc++.h> #define N 200010 #define LL long long #define IO ios::sync_with_stdio(0);cin.tie(0) using namespace std; struct edge { int x,y,w; bool operator < (const edge a) const { return w>a.w; } } e[N]; int n,m,f[N],fa[N],dep[N],pre[N]; int cnt[N][32][2],sz[N][32][2]; struct Edge{int y,w;}; vector<Edge> g[N]; vector<edge> G; int find(int x) { return f[x]==x?x:f[x]=find(f[x]); } void dfs(int x,int ff,int d) { fa[x]=ff; dep[x]=d; for(int i=0;i<g[x].size();i++) { int y=g[x][i].y; if (y==ff) continue; dfs(y,x,d+1); pre[y]=i; } } void init() { for(int i=1;i<N;i++) for(int j=0;j<31;j++) { cnt[i][j][0]=(i>>j)&1^1; cnt[i][j][1]=(i>>j)&1; } } int main() { IO; int T; cin>>T; init(); while(T--) { cin>>n>>m; G.clear(); for(int i=1;i<=n;i++) { f[i]=i,g[i].clear(); for(int j=0;j<31;j++) { sz[i][j][0]=cnt[i][j][0]; sz[i][j][1]=cnt[i][j][1]; } } for(int i=1;i<=m;i++) cin>>e[i].x>>e[i].y>>e[i].w; sort(e+1,e+1+m); //kruskal for(int i=1;i<=m;i++) { int x=e[i].x,y=e[i].y,w=e[i].w; if (find(x)!=find(y)) { f[find(x)]=find(y); g[x].push_back(Edge{y,w}); g[y].push_back(Edge{x,w}); } else G.push_back(edge{x,y,w}); } //get fa[] & pre[] & dep[] dfs(1,0,0); //delete the minimum edge in the circle for(int i=0;i<G.size();i++) { int x=G[i].x,y=G[i].y,w=G[i].w; if (dep[x]<dep[y]) swap(x,y); for(;dep[x]>dep[y];x=fa[x]) g[fa[x]][pre[x]].w+=w; for(;x!=y;x=fa[x],y=fa[y]) { g[fa[x]][pre[x]].w+=w; g[fa[y]][pre[y]].w+=w; } } //rebuild the graph and sort int tot=0; for(int i=1;i<=n;i++) for(int j=0;j<g[i].size();j++) if (dep[g[i][j].y]>dep[i]) e[++tot]=edge{i,g[i][j].y,g[i][j].w}; sort(e+1,e+1+tot); //initial dsu for(int i=1;i<=n;i++) f[i]=i; //calculate the answer unsigned long long ans=0; for(int i=1;i<=tot;i++) { int x=e[i].x,y=e[i].y,w=e[i].w; x=find(x); y=find(y); f[x]=y; for(int j=0;j<31;j++) { if ((w&(1LL<<j))) ans+=(1LL*sz[x][j][0]*sz[y][j][0]+1LL*sz[x][j][1]*sz[y][j][1])*(1LL<<j); else ans+=(1LL*sz[x][j][0]*sz[y][j][1]+1LL*sz[x][j][1]*sz[y][j][0])*(1LL<<j); sz[y][j][0]+=sz[x][j][0]; sz[y][j][1]+=sz[x][j][1]; } } cout<<ans<<endl; } return 0; }
相關推薦
HDU 6350 2018HDU多校賽 第五場 Always Online(圖論 + 並查集 + 組合計數)
大致題意:給你一個仙人掌圖,讓你計算:。 根據去年多校賽某一道題的經驗,很多仙人掌圖的問題,其實可以轉化為樹的問題。所以我們同樣考慮,如果這是一棵樹的話如何去做。注意到表示式裡面的flow(i,j)表示從i到j的最小割或最大流,而在樹上的最小
HDU 6327 2018HDU多校賽 第三場 Random Sequence(概率期望dp+數論)
Problem I. Random Sequence Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 524288/524288 K (Java/Others) Total Submissio
HDU 6340 2018HDU多校賽 第四場 Delightful Formulas(莫比烏斯反演+伯努利數+NTT+積性)
大致題意:給你k和m,還有n分解質因子之後的質因子及其對應的指數,讓你求 。 首先,這種含有gcd的式子,第一步肯定是進行莫比烏斯反演,這裡由於前面好幾篇都由類似的反演形式,所以我就不展開了,直接就得出反演之後的結果:
HDU 6338 2018HDU多校賽 第四場 Depth-First Search(組合數學+平衡樹/pbds)
大致題意:給你一個dfs序列B和一棵樹,現在讓你在這個樹上隨機選擇一個點,然後按照隨機的dfs順序走。問你最後能走出幾個dfs序列,是得該dfs序列字典序小於給定的dfs序B。 首先,我們考慮一棵樹有根樹他的dfs序有多少種。我們可以這麼考慮,對於任意點x,
HDU 6428 2018HDU多校賽 第十場 Calculate(莫比烏斯反演 + 積性 + 線性篩)
題意簡單粗暴,讓你求 。 與gcd有關,一般來說都是要上莫比烏斯來反演一下了。具體來說,我們先來推一些式子:
HDU 6416 2018HDU多校賽 第九場 Rikka with Seam(dp + 字首和優化)
大致題意:給你一個n*m的01矩陣,現在要讓你每一行和每一列都去掉一個數字,而且要求相鄰兩行之間去掉數字的位置的絕對值要小於等於k。現在問你刪除之後的矩形最多有幾種。 首先,我們一行一行考慮,對於同一行,顯然是看有多少個塊,有多少個塊就有多少個方案。然後對於
HDU多校賽第9場 HDU 4965Fast Matrix Calculation【矩陣運算+數學小知識】
stdin amp line you stream [] nbsp content ans 難度上。,,確實。。。不算難 問題是有個矩陣運算的優化 題目是說給個N*K的矩陣A給個K*N的矩陣B(1<=N<=1000 && 1=<K<
HDU 6314 2018HDU多校賽第二場 Matrix(容斥原理+組合計數)
Matrix Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 332768/332768 K (Java/Others) Total Submission(s): 445 Accepted Submiss
2017年多校賽第九場 1005 FFF at Valentine(縮點+拓撲排序)
其實縮點很容易想到,就是不怎麼會用拓撲排序所以一直卡著判斷這個地方。 程式碼如下: #include <stdio.h> #include <string.h> #include <vector> #include <s
2017年多校賽第九場 1006 Senior Pan(dijkstra套路題)
這道題有很多解法,我是按照題解的做法寫了一遍。 題意:給出一個有向圖,然後有k個點,問這k個點兩兩之間的最短距離的最小值是多少。 解法:題解是把k個點按照每個點二進位制位的不同分成兩個集合,然後求一次多源最短路。由於最大的數是1e5,所以也就到個。。。2^17的樣子?由於
2014多校聯合-第五場
1001:Inversion 模版題,求逆序數對。有多少逆序數對,就可以剪掉多少。 1003:Least common multiple 對於每一個子集,lcm為2的a的最大值次方*3的b的最大值次方。 所以我們只需要求出以某個b為b的最大值的時候,a的最大值的分佈情況即可
hdu6434 杭電多校賽 第十場 1009 I題 count
Problem I. Count Problem Description Multiple query, for each n, you need to get n i-1 ∑ ∑ [gcd(i + j, i - j) = 1] i=1 j=1 Input On th
牛客網多校訓練營第五場gpa(01分數規劃)
01分數規劃 01分數規劃問題:所謂的01分數規劃問題就是指這樣的一類問題,給定兩個陣列,a[i]表示選取i的收益,b[i]表示選取i的代價。如果選取i,定義x[i]=1否則x[i]=0。每一個物品只有選或者不選兩種方案,求一個選擇方案使得R=sigma(a[i]*x[
2018-2019賽季多校聯合新生訓練賽第五場(2018/12/14)補題題解
A 【字串】ISBN號碼(字串基礎) 字串基礎題,注意一下x的特判即可 程式碼 #include <bits/stdc++.h> using namespace std; int main() { ios::sync_with_stdio(0); cin.tie(0); cout
HDU 5399 Too Simple (2015年多校比賽第9場)
assert vector math php post long long size 答案 ring 1.題目描寫敘述:點擊打開鏈接 2.解題思路:本題分情況討論。比賽時候真是想的太簡單了。以為就是(n!)^(cnt-1)。終於無限WA。本題有幾個特殊情況須要額外推斷。
HDU 5411 CRB and Puzzle (2015年多校比賽第10場)
理解 tor for truct rac iostream blank 全部 sta 1.題目描寫敘述:pid=5411">點擊打開鏈接 2.解題思路:本題實際是是已知一張無向圖。問長度小於等於m的路徑一共同擁有多少條。能夠通過建立轉移矩陣利用矩陣高速冪解決。當中
2017多校聯合第9場1010 Two String/hdu 6170(正則表示式/dp)
Two strings Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 680 Accepted Su
2017多校聯合第十場/HDU 6171 Admiral 雙向bfs + 雜湊
Suppose that you are an admiral of a famous naval troop. Our naval forces have got 21 battleships. There are 6 types of battleships. First, we have got on
2017多校訓練賽第一場 HDU 6039 Gear Up(線段樹+並查集)
Gear Up Time Limit: 8000/4000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others) Total Submission(s): 59 Accepted Submiss
hdu 4911 Inversion(歸併排序求逆序對數)2014多校訓練第5場
Inversion Time Limit: 2000/1000 MS (Java/Others) Memory L