codeforces 962E Byteland, Berland and Disputed Cities 最小生成树变形
題目
題目鏈接
題意
在OxOx軸上有一堆點,這些點有三種類型R、B、PR、B、P型,現在要求添加一些線段把這些點連起來,使得如果去掉RR類型點,剩下的點都是聯通的。如果去掉BB類型的點,剩下的點也是聯通的,求最小的邊長度總和。
題解
如果我們單單只看去掉R(B)R(B)類型的點的時候,這道題毫無疑問是一道最小生成樹的題目,實際上也并不需要用一些最小生成樹的做法來做,只需要按順序掃一遍就好了。
但這個題不是,它要求這個圖去掉R(B)R(B)類型的點之后,都仍舊是最小生成樹。
我們稱這張圖為二樹圖(我胡起的,只是方便后面敘述,實際上并沒有這個名字)。
那么如何構造這個二樹圖呢,我們采用歸納法。
我們從左向右掃描所得到的點,并且假設在所掃描過的點中已經過構造好了部分二樹圖。
那么對于我們當前正在掃描的點,該怎么進行處理呢?
當前的點是B(R)B(R)點,那么我們需要把這個B(R)B(R)點與前面最近的B(R)B(R)點或者最近的PP點相連接,這樣的話保證了去掉R(B)R(B)點之后,當前的這個B(R)B(R)點連接到了生成樹中,這樣保持了二樹圖的性質。
當前的點是PP點,這種情況有點復雜,因為PP點是不會被去掉的,所以PP點影響了兩種生成樹。我們這樣考慮,為了保證兩個生成樹都要連接到當前的這個PP點,對于去掉B(R)B(R)點得到的生成樹,想要連接PP,那么我們一定要讓這個PP連接到最近的R(B)R(B)或者PP點上,如果最近的是PP點,那么直接連接就好了,因為PP連接到了前面的PP點上,那么這個PP將同時連接到兩顆生成樹上去。
而如果PP到兩顆樹最近的點都不是PP點(即上一個PP與當前PP點之間即有BB點也有RR點這種情況),我們首先讓當前的PP點連接最近的BB點和最近的RR點,在讓當前的PP點與前一個PP點相連,這樣的話,對于兩顆生成樹來說都產生了一個圈,為了保持生成樹的性質,我們需要破圈。如果我們此時破了P?PP?P邊,那么獲得優勢是cost(Pnow,Ppre)cost(Pnow,Ppre),保證是二樹圖,結束。如果我們不破P?PP?P邊,那么我們勢必要在兩個圈中各找一個最大的Bx?Bx+1Bx?Bx+1和Ry?Ry+1Ry?Ry+1破掉,獲得優勢cost(Bx,Bx+1)+cost(Ry,Ry+1)cost(Bx,Bx+1)+cost(Ry,Ry+1),保證是二樹圖,結束。因此我們比較那個優勢大就選擇那種破法。
本題至此就解決了。
代碼
#include <iostream> #include <cstdio> using namespace std; const int maxn = 2e5+7; typedef long long ll; ll B,R,mxB,mxR,P,ans; int n; int main(){cin>>n;for(int i = 1;i <= n;++i){ll x;char c;scanf("%lld %c",&x,&c);x += 1e9+7;if(c == 'B'){if(B) ans += x - B,mxB = max(mxB,x - B);B = x; }if(c == 'R'){if(R) ans += x - R,mxR = max(mxR,x - R);R = x;}if(c == 'P'){if(B) mxB = max(mxB,x - B),ans += x-B;if(R) mxR = max(mxR,x - R),ans += x-R;if(P) {ans += min(0ll,x - P - mxB - mxR);}B = R = P = x;mxB = mxR = 0;}}cout<<ans<<endl;return 0; }總結
以上是生活随笔為你收集整理的codeforces 962E Byteland, Berland and Disputed Cities 最小生成树变形的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 无线路由器怎么更改网速路由器怎么设置无线
- 下一篇: 如何压缩pdf文件的大小pdf怎么压缩文