1. 程式人生 > >[HDU6271]Master of Connected Component

[HDU6271]Master of Connected Component

tac 表示 swa dfs div HA IT math 多少

[HDU6271]Master of Connected Component

題目大意:

給出兩棵\(n(n\le10000)\)個結點的以\(1\)為根的樹\(T_a,T_b\),和一個擁有\(m(m\le10000)\)個結點的圖\(G\)\(T_a,T_b\)的每一個結點上都有一個信息,表示\(G\)中的一條邊\((u_i,v_i)\)。對於\(i\in[1,n]\),詢問從\(T_a\)\(T_b\)上分別取出鏈\(1\sim i\),將鏈上的信息所表示的邊加入\(G\)中後,\(G\)中共有多少連通塊。

思路:

對於\(T_a\)分塊,對於\(T_a\)中的每一塊,在\(T_b\)上DFS,若當前結點是\(T_a\)

當前塊內結點,則暴力加入\(T_b\)中所需要的邊進行統計。加邊、刪邊操作用棧記錄並查集合並情況,並查集只按秩合並,不路徑壓縮,實現可拆分並查集。時間復雜度\(O(n\sqrt n\log n)\)

源代碼:

#include<cmath>
#include<stack>
#include<cstdio>
#include<cctype>
#include<vector>
#include<numeric>
inline int getint() {
    register char ch;
    while(!isdigit(ch=getchar()));
    register
int x=ch^'0'; while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0'); return x; } constexpr int N=10001; int n,m,lim,ans[N],par[2][N],dep[N],dfn[N]; std::pair<int,int> w[2][N]; std::vector<int> e[2][N]; inline void clear() { dfn[0]=0; for(register int
t=0;t<2;t++) { for(register int i=1;i<=n;i++) { e[t][i].clear(); e[t][i].shrink_to_fit(); } } std::fill(&ans[1],&ans[n]+1,0); } int top; std::pair<int*,int> stack[N*4]; inline void push(int &x) { stack[++top]={&x,x}; } inline void back(const int &tmp) { for(;tmp<top;top--) { *stack[top].first=stack[top].second; } } class DisjointSet { private: int anc[N],size[N]; int find(const int &x) { return x==anc[x]?x:find(anc[x]); } public: void reset() { std::iota(&anc[1],&anc[m+1],1); std::fill(&size[1],&size[m+1],1); } void merge(const int &x,const int &y) { int p=find(x),q=find(y); if(p==q) return; if(size[p]>size[q]) std::swap(p,q); push(anc[p]); push(size[q]); anc[p]=q; size[q]+=size[p]; } }; DisjointSet s; void solve(const int &x,const int &t) { const int tmp=top; s.merge(w[1][x].first,w[1][x].second); if(ans[x]==-1&&dfn[x]>=dfn[t]) { const int tmp=top; for(register int y=x;y!=t;y=par[0][y]) { s.merge(w[0][y].first,w[0][y].second); } ans[x]=m-top/2; back(tmp); } for(auto &y:e[1][x]) { solve(y,t); } back(tmp); } void dfs(const int &x) { const int tmp=top; s.merge(w[0][x].first,w[0][x].second); dep[x]=1; dfn[x]=++dfn[0]; for(auto &y:e[0][x]) { dfs(y); dep[x]=std::max(dep[x],dep[y]+1); } ans[x]=-1; if(dep[x]==lim||x==1) { solve(1,x); dep[x]=0; } back(tmp); } int main() { for(register int T=getint();T;T--) { n=getint(),m=getint(),lim=sqrt(n); for(register int t=0;t<2;t++) { for(register int i=1;i<=n;i++) { w[t][i]={getint(),getint()}; } for(register int i=1;i<n;i++) { const int u=getint(),v=getint(); par[t][v]=u; e[t][u].push_back(v); } } s.reset(); dfs(1); for(register int i=1;i<=n;i++) { printf("%d\n",ans[i]); } clear(); } return 0; }

[HDU6271]Master of Connected Component