[HDU6271]Master of Connected Component

[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;
}

原文地址:https://www.cnblogs.com/skylee03/p/9099741.html

时间: 2024-08-29 17:34:49

[HDU6271]Master of Connected Component的相关文章

HDU 6271 Master of Connected Component(2017 CCPC 杭州 H题,树分块 + 并查集的撤销)

题目链接  2017 CCPC Hangzhou Problem H 思路:对树进行分块.把第一棵树分成$\sqrt{n}$块,第二棵树也分成$\sqrt{n}$块.    分块的时候满足每个块是一个连通块,那么每个块就有一个共同的祖先. 把询问按照第一个点被第一棵树的哪个祖先管辖和第二个点被第二棵树的哪个祖先管辖,分成$n$类. 每一类询问一起处理,处理完后用可撤销并查集恢复到之前的状态. 每一类询问之间依次转移,每次转移,移动次数不会超过$\sqrt{n}$次. 最后总时间复杂度$O(n^{

[LintCode] Find the Connected Component in the Undirected Graph

Find the Connected Component in the Undirected Graph Find the number connected component in the undirected graph. Each node in the graph contains a label and a list of its neighbors. (a connected component (or just component) of an undirected graph i

[LintCode] Find the Weak Connected Component in the Directed Graph

Find the number Weak Connected Component in the directed graph. Each node in the graph contains a label and a list of its neighbors. (a connected set of a directed graph is a subgraph in which any two vertices are connected by direct edge path.) Exam

[email&#160;protected] Strongly Connected Component

Strongly Connected Components A directed graph is strongly connected if there is a path between all pairs of vertices. A strongly connected component (SCC) of a directed graph is a maximal strongly connected subgraph. For example, there are 3 SCCs in

Connected Component in Undirected Graph

Description Find connected component in undirected graph. Each node in the graph contains a label and a list of its neighbors. (A connected component of an undirected graph is a subgraph in which any two vertices are connected to each other by paths,

Find the Weak Connected Component in the Directed Graph

Description Find the number Weak Connected Component in the directed graph. Each node in the graph contains a label and a list of its neighbors. (a weak connected component of a directed graph is a maximum subgraph in which any two vertices are conne

lintcode 容易题:Find the Connected Component in the Undirected Graph 找出无向图汇总的相连要素

题目: 找出无向图汇总的相连要素 请找出无向图中相连要素的个数. 图中的每个节点包含其邻居的 1 个标签和 1 个列表.(一个无向图的相连节点(或节点)是一个子图,其中任意两个顶点通过路径相连,且不与超级图中的其它顶点相连.) 样例 给定图: A------B C \ | | \ | | \ | | \ | | D E 返回 {A,B,D}, {C,E}.其中有 2 个相连的元素,即{A,B,D}, {C,E} 解题: 广度优先+递归,写不出来,程序来源 Java程序: /** * Defini

题解 CF1196E Connected Component on a Chessboard

感觉这题还可以 因为总空间比输入数量 不知高到哪里去了 ,所以完全不需要考虑放不下的问题 从贪心的角度考虑,如果要使相差数量巨大的\(b\)和\(w\)能够成功放下来,应该使这些方块尽量分散(似乎有点抽象) 来一发图解 作者因为太懒于是决定直接以B表示黑色,W表示白色 假设有一组方块拼成了一个正方形,如图 BWB WBW BWB 那么在不改变白块数量的情况下,最多还能加\(4\)个黑块,分别连在四个白块旁边 但是如果拉成直线,如图 BWBWBWBWB 发现可以在两边总共加\(8\)个黑块了,因为

Giraph添加应用程序Weakly Connected Components算法

本人原创,转载请注明出处! 本人QQ:530422429,欢迎大家指正.讨论. 目的:举例说明如何在Giraph中添加应用程序,以WCC(Weakly Connected Components)算法为例,描述怎么添加Vertex的子类,自定义输入输出格式和使用Combiner等. 背景:Giraph源码中自带有WCC算法,类为:org.apache.giraph.examples.ConnectedComponentsVertex,代码如下: package org.apache.giraph.