生活随笔
收集整理的這篇文章主要介紹了
P3206 [HNOI2010]城市建设
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
P3206 [HNOI2010]城市建設(shè)
題目描述
無(wú)向圖上修改邊權(quán),動(dòng)態(tài)維護(hù)MSTMSTMST,求每次修改后的MST的權(quán)值和。
Solution
有一個(gè)簡(jiǎn)單好想的做法——LCTLCTLCT+線段樹分治。
考慮每次加邊,若形成了一個(gè)環(huán),則把環(huán)上最大的一條邊刪掉,LCTLCTLCT維護(hù)。
然后刪邊就套一個(gè)線段樹分治,刪邊操作就變成了加邊和回退操作,直接做就行了。
時(shí)間復(fù)雜度:大常數(shù)O(nlg2n)O(nlg^2n)O(nlg2n),似乎卡不過。
還有一個(gè)神奇的做法。
因?yàn)橐淮涡薷牟僮髦粫?huì)改動(dòng)MST上的一條邊,所以我們考慮通過線段樹分治,分治區(qū)間為[l,r][l,r][l,r],將點(diǎn)數(shù)和邊數(shù)都保持在O(r?l)O(r-l)O(r?l)級(jí)別。
設(shè)[l,r][l,r][l,r]中的操作涉及的邊集為SSS,當(dāng)前點(diǎn)集為VVV,當(dāng)前邊集(不包含SSS中的邊)為EEE
有兩個(gè)顯然的引理:
1.把SSS的邊權(quán)值都設(shè)為INFINFINF,將其設(shè)為S′S'S′,在(V,E+S′)(V,E+S')(V,E+S′)跑MSTMSTMST,顯然若此時(shí)不在MSTMSTMST中的邊在之后的分治過程中都不可能在MSTMSTMST中了,直接在EEE刪去即可。
2.把SSS的邊權(quán)值都設(shè)為?INF-INF?INF,將其設(shè)為S′′S''S′′,在(V,E+S′′)(V,E+S'')(V,E+S′′)跑MSTMSTMST,顯然若此時(shí)在MSTMSTMST中的邊在之后的分治過程中都一定在MSTMSTMST中了,直接在EEE刪去,并加上貢獻(xiàn)。
通過這兩個(gè)引理就可以讓∣E∣,∣V∣=O(r?l)|E|,|V|=O(r-l)∣E∣,∣V∣=O(r?l)。
時(shí)間復(fù)雜度T(n)=T(n/2)+O(nlgn)=O(nlg2n)T(n)=T(n/2)+O(nlgn)=O(nlg^2n)T(n)=T(n/2)+O(nlgn)=O(nlg2n),常數(shù)比較小。
#include <vector>
#include <list>
#include <map>
#include <set>
#include <deque>
#include <queue>
#include <stack>
#include <bitset>
#include <algorithm>
#include <functional>
#include <numeric>
#include <utility>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <cctype>
#include <string>
#include <cstring>
#include <ctime>
#include <cassert>
#include <string.h>
#define MP(A,B) make_pair(A,B)
#define PB(A) push_back(A)
#define SIZE(A) ((int)A.size())
#define LEN(A) ((int)A.length())
#define FOR(i,a,b) for(int i=(a);i<(b);++i)
#define fi first
#define se secondusing namespace std
;template<typename T
>inline bool upmin(T
&x
,T y
) { return y
<x
?x
=y
,1:0; }
template<typename T
>inline bool upmax(T
&x
,T y
) { return x
<y
?x
=y
,1:0; }typedef long long ll
;
typedef unsigned long long ull
;
typedef long double lod
;
typedef pair
<int,int> PR
;
typedef vector
<int> VI
;const lod eps
=1e-11;
const lod pi
=acos(-1);
const int oo
=1<<30;
const ll loo
=1ll<<62;
const int mods
=998244353;
const int MAXN
=50005;
const int INF
=0x3f3f3f3f;
inline int read()
{int f
=1,x
=0; char c
=getchar();while (c
<'0'||c
>'9') { if (c
=='-') f
=-1; c
=getchar(); }while (c
>='0'&&c
<='9') { x
=(x
<<3)+(x
<<1)+(c
^48); c
=getchar(); }return x
*f
;
}
PR a
[MAXN
];
int flag
[MAXN
],Flag
[MAXN
],fa
[MAXN
],vn
[18],en
[18],V
[18][MAXN
],To
[MAXN
],b
[MAXN
];
struct enode
{ int u
,v
,c
,id
; } e
[MAXN
],E
[18][MAXN
],tmp
[MAXN
];
inline int compareE(enode x
,enode y
) { return x
.c
<y
.c
; }
inline int find(int x
) { return fa
[x
]==x
?fa
[x
]:fa
[x
]=find(fa
[x
]); }
inline void work1(int n
,int m
,int l
,int r
,int dep
)
{for (int i
=l
;i
<=r
;i
++) flag
[a
[i
].fi
]=1;for (int i
=1;i
<=m
;i
++){tmp
[i
]=E
[dep
][i
];if (flag
[E
[dep
][i
].id
]) tmp
[i
].c
=INF
;}sort(tmp
+1,tmp
+m
+1,compareE
);for (int i
=1;i
<=n
;i
++) fa
[i
]=i
;for (int i
=1;i
<=m
;i
++){int x
=find(tmp
[i
].u
),y
=find(tmp
[i
].v
),c
=tmp
[i
].c
;if (x
!=y
) fa
[x
]=y
;else if (c
!=INF
) Flag
[tmp
[i
].id
]=-1;}for (int i
=l
;i
<=r
;i
++) flag
[a
[i
].fi
]=0;
}
inline void work2(int n
,int m
,int l
,int r
,int dep
)
{for (int i
=l
;i
<=r
;i
++) flag
[a
[i
].fi
]=1;for (int i
=1;i
<=m
;i
++){tmp
[i
]=E
[dep
][i
];if (flag
[E
[dep
][i
].id
]) tmp
[i
].c
=-INF
;}sort(tmp
+1,tmp
+m
+1,compareE
);for (int i
=1;i
<=n
;i
++) fa
[i
]=i
;for (int i
=1;i
<=m
;i
++){int x
=find(tmp
[i
].u
),y
=find(tmp
[i
].v
),c
=tmp
[i
].c
;if (x
!=y
) {fa
[x
]=y
;if (c
!=-INF
) Flag
[tmp
[i
].id
]=1;}}for (int i
=l
;i
<=r
;i
++) flag
[a
[i
].fi
]=0;
}
inline void solve(int l
,int r
,int dep
,ll Ans
)
{int n
=vn
[dep
],m
=en
[dep
];if (l
==r
){for (int i
=1;i
<=m
;i
++){tmp
[i
]=E
[dep
][i
];if (tmp
[i
].id
==a
[l
].fi
) tmp
[i
].c
=a
[l
].se
;}sort(tmp
+1,tmp
+m
+1,compareE
);for (int i
=1;i
<=n
;i
++) fa
[i
]=i
;for (int i
=1;i
<=m
;i
++){int x
=find(tmp
[i
].u
),y
=find(tmp
[i
].v
),c
=tmp
[i
].c
;if (x
!=y
) fa
[x
]=y
,Ans
+=c
;}printf("%lld\n",Ans
);return;}for (int i
=1;i
<=m
;i
++) Flag
[E
[dep
][i
].id
]=0;work1(n
,m
,l
,r
,dep
);work2(n
,m
,l
,r
,dep
);vn
[dep
+1]=en
[dep
+1]=0;for (int i
=1;i
<=n
;i
++) fa
[i
]=i
;for (int i
=1;i
<=m
;i
++)if (Flag
[E
[dep
][i
].id
]==1) {int x
=find(E
[dep
][i
].u
),y
=find(E
[dep
][i
].v
);if (x
!=y
) fa
[x
]=y
;}for (int i
=1;i
<=n
;i
++) if (fa
[i
]==i
) V
[dep
+1][++vn
[dep
+1]]=V
[dep
][i
],To
[i
]=vn
[dep
+1];for (int i
=1;i
<=m
;i
++)if (Flag
[E
[dep
][i
].id
]==1) Ans
+=E
[dep
][i
].c
;else if (Flag
[E
[dep
][i
].id
]==0) {int x
=find(E
[dep
][i
].u
),y
=find(E
[dep
][i
].v
);if (x
!=y
) E
[dep
+1][++en
[dep
+1]]=(enode
){To
[x
],To
[y
],E
[dep
][i
].c
,E
[dep
][i
].id
};}int mid
=(l
+r
)>>1;solve(l
,mid
,dep
+1,Ans
);for (int i
=l
;i
<=mid
;i
++) b
[a
[i
].fi
]=a
[i
].se
;for (int i
=1;i
<=en
[dep
+1];i
++)if (b
[E
[dep
+1][i
].id
]!=INF
) E
[dep
+1][i
].c
=b
[E
[dep
+1][i
].id
];for (int i
=l
;i
<=mid
;i
++) b
[a
[i
].fi
]=INF
;solve(mid
+1,r
,dep
+1,Ans
);
}
int main()
{int n
=read(),m
=read(),q
=read();for (int i
=1;i
<=m
;i
++) {int u
=read(),v
=read(),c
=read();e
[i
]=(enode
){u
,v
,c
,i
};}for (int i
=1;i
<=q
;i
++){int x
=read(),y
=read();a
[i
]=MP(x
,y
);}vn
[0]=n
,en
[0]=m
;for (int i
=1;i
<=n
;i
++) V
[0][i
]=i
;for (int i
=1;i
<=m
;i
++) E
[0][i
]=e
[i
],b
[i
]=INF
;solve(1,q
,0,0);return 0;
}
代碼有點(diǎn)丑……
創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來(lái)咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)
總結(jié)
以上是生活随笔為你收集整理的P3206 [HNOI2010]城市建设的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。